网络流模版
来源:互联网 发布:轻淘客 登录淘宝联盟 编辑:程序博客网 时间:2024/06/05 20:02
九野的博客,转载请注明出处 : http://blog.csdn.net/acmmmm/article/details/11199941
特别注意:若是需要双向边,则addedge中第二个edge(反向弧) 的cap应该为cap而不是0
如:http://acm.hdu.edu.cn/showproblem.php?pid=3870 (此题虽用网络流容易超时,但网络流的建图十分巧妙,要符合上述规定)
特别注意:无向图并不是加2条边,而是加一条边。在sap模版中是把rw参数填上
dinic模版中是把add函数修改一下。
/*无源汇上下界网络流:构图如下:1、首先对于与每条边(u,v,L,H),u->v连一条容量为H-L的边2、创建一个源S,和汇T3、对于任意一个结点,如果u出边下界和 OutL > 入边下界和InL,则u->T一条OutL - InL的边。否则连S->u一条InL-OutL的边。4、求s-t最大流,若与S关联的边满容量,则有解。则残余网络中u->v的流量+其原来图的下界构成一个可行流*//*有源汇(S T)上下界最小流像无源无汇上下界可行流那样先建好图,记图的超级源点为SS,超级汇点为TT。先从SS到TT跑一遍最大流,然后加边T->S容量为无穷大,然后再从SS到TT跑一遍最大流,若与SS关联的边满容量,则有解。其中最小流为最后加进去的n→1的边的流量,找边的流量跟无源无汇上下界可行流一样,否则无解。*//*有源汇(S T)上下界最大流像无源无汇上下界可行流那样先建好图,记图的超级源点为SS,超级汇点为TT。然后T到S连一条边,容量为无穷大。从SS->TT跑一遍最大流 判可行性最后从源点S到汇点T跑一遍最大流就是答案,每条边容量的取法和无源无汇上下界可行流一样。*//*最大权闭合图正点权->负点权的边是约束条件(取了这个 正点权必须取哪些点)正点权割边(源点->正点权)表示该点不选负点权割边(负点权->汇点)表示该点选*/
Dinic:
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;//点标 [0,n]const int N = 200010;const int M = 500010;const int INF = ~0u >> 2;template<class T>struct Max_Flow { int n; int Q[N], sign; int head[N], level[N], cur[N], pre[N]; int nxt[M], pnt[M], E; T cap[M]; void Init(int n) { this->n = n+1; E = 0; std::fill(head, head + this->n, -1); } //有向rw 就= 0 void add(int from, int to, T c, T rw) { pnt[E] = to; cap[E] = c; nxt[E] = head[from]; head[from] = E++; pnt[E] = from; cap[E] = rw; nxt[E] = head[to]; head[to] = E++; } bool Bfs(int s, int t) { sign = t; std::fill(level, level + n, -1); int *front = Q, *tail = Q; *tail++ = t; level[t] = 0; while(front < tail && level[s] == -1) { int u = *front++; for(int e = head[u]; e != -1; e = nxt[e]) { if(cap[e ^ 1] > 0 && level[pnt[e]] < 0) { level[pnt[e]] = level[u] + 1; *tail ++ = pnt[e]; } } } return level[s] != -1; } void Push(int t, T &flow) { T mi = INF; int p = pre[t]; for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) { mi = std::min(mi, cap[p]); } for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) { cap[p] -= mi; if(!cap[p]) { sign = pnt[p ^ 1]; } cap[p ^ 1] += mi; } flow += mi; } void Dfs(int u, int t, T &flow) { if(u == t) { Push(t, flow); return ; } for(int &e = cur[u]; e != -1; e = nxt[e]) { if(cap[e] > 0 && level[u] - 1 == level[pnt[e]]) { pre[pnt[e]] = e; Dfs(pnt[e], t, flow); if(level[sign] > level[u]) { return ; } sign = t; } } } T Dinic(int s, int t) { pre[s] = -1; T flow = 0; while(Bfs(s, t)) { std::copy(head, head + n, cur); Dfs(s, t, flow); } return flow; }};Max_Flow <int>F;
isap:
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<vector>using namespace std;#define ll intconst int MAXN = 100010;//点数的最大值const int MAXM = 400010;//边数的最大值const int INF = 0x3f3f3f3f;struct Edge{ int to,next,cap,flow;}edge[MAXM];//注意是MAXMint tol;int head[MAXN];int gap[MAXN],dep[MAXN],cur[MAXN];void add(int u,int v,int w,int rw = 0){ edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;}int Q[MAXN];void BFS(int start,int end){ memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while(front != rear) { int u = Q[front++]; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } }}int S[MAXN];int sap(int start,int end,int N){ BFS(start,end); memcpy(cur,head,sizeof(head)); int top = 0; int u = start; int ans = 0; while(dep[start] < N) { if(u == end) { int Min = INF; int inser; for(int i = 0;i < top;i++) if(Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for(int i = 0;i < top;i++) { edge[S[i]].flow += Min; edge[S[i]^1].flow -= Min; } ans += Min; top = inser; u = edge[S[top]^1].to; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = i; break; } } if(flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if(u != start)u = edge[S[--top]^1].to; } return ans;}void init(){ tol = 0; memset(head,-1,sizeof(head)); }
Dinic 递归版:
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<stdio.h>#include<iostream>#include<algorithm>#include<queue>#include<cstring>#include<vector>#include<set>#include<cmath>using namespace std;#define inf 1073741824#define N 500 #define M 100100//N为点数 M为边数struct Edge{int from, to, cap, nex;}edge[M * 2];//双向边,注意RE 注意这个模版是 相同起末点的边 同时有效而不是去重int head[N], tot;//2个要初始化-1和0void add(int u, int v, int cap, int rw = 0){//网络流要加反向弧,即u->v 为10 则 v->u为 -10Edge E = { u, v, cap, head[u] };edge[tot] = E;head[u] = tot++;Edge E2 = { v, u, rw, head[v] }; //如果是无向边则rw的参数值和cap相同(即 add(u,v,cap,cap) ),若是有向边则rw不写(即 add(u,v,cap); )edge[tot] = E2;head[v] = tot++;}int dis[N], cur[N];//dis[i]表示i点距离起点的距离 cur[i]表示i点所连接的边中 正在考虑的边 优化不再考虑已经用过的点 初始化为headbool vis[N];bool BFS(int Start, int End){//跑一遍最短路memset(vis, 0, sizeof(vis));memset(dis, -1, sizeof(dis));queue<int>Q;Q.push(Start);dis[Start] = 0;vis[Start] = 1;while (!Q.empty()){int u = Q.front(); Q.pop();for (int i = head[u]; i != -1; i = edge[i].nex){Edge E = edge[i];if (!vis[E.to] && E.cap > 0){vis[E.to] = true;dis[E.to] = dis[u] + 1;if (E.to == End) return true;Q.push(E.to);}}}return false;}int DFS(int x, int a, int End){//当前 流入x 的流量是a 流量a 是所有流过边中 边权的最小值if (x == End || a == 0)return a;int flow = 0, f; //flow表示从x点流到下面所有点,最大的流量for (int& i = cur[x]; i != -1; i = edge[i].nex){Edge& E = edge[i];if (dis[x] + 1 == dis[E.to] && (f = DFS(E.to, min(a, E.cap), End))>0){E.cap -= f;edge[i ^ 1].cap += f;//反向边要减掉flow += f;a -= f;if (a == 0)break;}}return flow;}int Dinic(int Start, int End){int flow = 0;while (BFS(Start, End)){ //当存在源点到汇点的路径时memcpy(cur, head, sizeof(head));//把head的数组复制过去flow += DFS(Start, inf, End);}return flow;}void init(){ memset(head, -1, sizeof head); tot = 0; }
- 网络流模版
- 网络流模版
- 网络流模版
- 网络流模版
- 网络流---EK模版
- 网络流模版
- 费用流&网络流模版
- 网络流&费用流模版
- Hdu 1532 网络流模版
- 网络流各种算法模版
- poj 3469(网络流模版)
- 网络流(模版+例题)
- [模版] 网络流最大流、费用流
- 网络流之 最大流模版
- 网络流模版(Dinic算法)
- 网络流DINIC 递归版模版
- POJ 1273 Drainage Ditches 网络流模版
- 网络流DINIC递归版模版
- Qemu, Spice 消息模型
- Asp:chart 控件画柱状图和饼图
- 分类算法之朴素贝叶斯分类(Naive Bayesian classification)
- 在Robotium中使用ID
- Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形)
- 网络流模版
- spice client 和 spice server 通信机制
- Java中发邮件的6种方法
- Hibernate一对多和多对一关系详解 (转载)
- iOS中UIPopoverController的使用
- 有关C++中的流操纵算子
- C语言中常用字符串函数锦囊
- mysql group by用法
- spring mvc中org.springframework.web.servlet.DispatcherServlet类