网络流模板
来源:互联网 发布:自己编曲的软件 编辑:程序博客网 时间:2024/05/17 07:58
Edmond Karp 算法:
#include <iostream>#include <queue>#include<string.h>using namespace std;#define arraysize 201int maxData = 0x7fffffff;int capacity[arraysize][arraysize]; //记录残留网络的容量int flow[arraysize]; //标记从源点到当前节点实际还剩多少流量可用int pre[arraysize]; //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中int n,m;queue<int> myqueue;int BFS(int src,int des){ int i,j; while(!myqueue.empty()) //队列清空 myqueue.pop(); for(i=1;i<m+1;++i) { pre[i]=-1; } pre[src]=0; flow[src]= maxData; myqueue.push(src); while(!myqueue.empty()) { int index = myqueue.front(); myqueue.pop(); if(index == des) //找到了增广路径 break; for(i=1;i<m+1;++i) { if(i!=src && capacity[index][i]>0 && pre[i]==-1) { pre[i] = index; //记录前驱 flow[i] = min(capacity[index][i],flow[index]); //关键:迭代的找到增量 myqueue.push(i); } } } if(pre[des]==-1) //残留图中不再存在增广路径 return -1; else return flow[des];}int EK(int src,int des){ int increasement= 0; int sumflow = 0; while((increasement=BFS(src,des))!=-1) { int k = des; //利用前驱寻找路径 while(k!=src) { int last = pre[k]; capacity[last][k] -= increasement; //改变正向边的容量 capacity[k][last] += increasement; //改变反向边的容量 k = last; } sumflow += increasement; } return sumflow;}int main(){ int i,j; int start,end,ci; while(cin>>n>>m) { memset(capacity,0,sizeof(capacity)); memset(flow,0,sizeof(flow)); for(i=0;i<n;++i) { cin>>start>>end>>ci; if(start == end) //考虑起点终点相同的情况 continue; capacity[start][end] +=ci; //此处注意可能出现多条同一起点终点的情况(重边) } cout<<EK(1,m)<<endl; } return 0;}
Dinic非递归版:
#define N 5000#define M 1505#define inf 536870912//N为点数 M为边数struct Edge{int from, to, cap, nex;}edge[M*10];//注意这个一定要够大 不然会re 还有反向弧int head[N], edgenum;void addedge(int u, int v, int cap){Edge E = { u, v, cap, head[u]};edge[ edgenum ] = E;head[u] = edgenum ++;Edge E2= { v, u, 0, head[v]};edge[ edgenum ] = E2;head[v] = edgenum ++;}int sign[N], s, t;bool BFS(int from, int to){memset(sign, -1, sizeof(sign));sign[from] = 0;queue<int>q;q.push(from);while( !q.empty() ){int u = q.front(); q.pop();for(int i = head[u]; i!=-1; i = edge[i].nex){int v = edge[i].to;if(sign[v]==-1 && edge[i].cap){sign[v] = sign[u] + 1, q.push(v);if(sign[to] != -1)return true;}}}return false;}int Stack[M*4], top, cur[M*4];int dinic(){int ans = 0;while( BFS(s, t) ){memcpy(cur, head, sizeof(head));int u = s;top = 0;while(1){if(u == t){int flow = inf, loc;//loc 表示 Stack 中 cap 最小的边for(int i = 0; i < top; i++)if(flow > edge[ Stack[i] ].cap){flow = edge[Stack[i]].cap;loc = i;}for(int i = 0; i < top; i++){edge[ Stack[i] ].cap -= flow;edge[Stack[i]^1].cap += flow;}ans += flow;top = loc;u = edge[Stack[top]].from;}for(int i = cur[u]; i!=-1; cur[u] = i = edge[i].nex)//cur[u] 表示u所在能增广的边的下标if(edge[i].cap && (sign[u] + 1 == sign[ edge[i].to ]))break;if(cur[u] != -1){Stack[top++] = cur[u];u = edge[ cur[u] ].to;}else{if( top == 0 )break;sign[u] = -1;u = edge[ Stack[--top] ].from;}}}return ans;}
Dinic 递归版:
#define inf 1000000#define N 1000 #define M 100000//N为点数 M为边数inline int Min(int a,int b){return a>b?b:a;} //注意这个类型是intstruct Edge{int from, to, cap, nex;}edge[M*2];//双向边,注意RE 注意这个模版是 相同起末点的边 同时有效而不是去重int head[N],edgenum;//2个要初始化-1和0void addedge(int u, int v, int cap){//网络流要加反向弧,即u->v 为10 则 v->u为 -10Edge E = {u, v, cap, head[u]};edge[ edgenum ] = E;head[ u ] = edgenum++;Edge E2 = {v, u, 0, head[v]}; //这里的cap若是单向边要为0edge[ edgenum ] = E2;head[ v ] = edgenum++;}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 Maxflow(int Start,int End){int flow=0; while(BFS(Start,End)){ //当存在源点到汇点的路径时memcpy(cur,head,sizeof(head));//把head的数组复制过去flow += DFS(Start, inf, End);}return flow;}
ISAP 版:
typedef struct {int v, next, val;} edge;const int MAXN = 20010;const int MAXM = 500010; edge e[MAXM];int p[MAXN], eid; inline void init() {memset(p, -1, sizeof(p));eid = 0;} //有向inline void insert1(int from, int to, int val) {e[eid].v = to;e[eid].val = val;e[eid].next = p[from];p[from] = eid++; swap(from, to); e[eid].v = to;e[eid].val = 0;e[eid].next = p[from];p[from] = eid++;} //无向inline void insert2(int from, int to, int val) {e[eid].v = to;e[eid].val = val;e[eid].next = p[from];p[from] = eid++; swap(from, to); e[eid].v = to;e[eid].val = val;e[eid].next = p[from];p[from] = eid++;} int n, m; //n为点数 m为边数int h[MAXN];int gap[MAXN]; int source, sink;inline int dfs(int pos, int cost) {if (pos == sink) {return cost;} int j, minh = n - 1, lv = cost, d; for (j = p[pos]; j != -1; j = e[j].next) {int v = e[j].v, val = e[j].val; if(val > 0) {if (h[v] + 1 == h[pos]) {if (lv < e[j].val) {d = lv;} else {d = e[j].val;} d = dfs(v, d);e[j].val -= d;e[j ^ 1].val += d;lv -= d; if (h[source] >= n) {return cost - lv;} if (lv == 0) {break;}} if (h[v] < minh){minh = h[v];}}} if (lv == cost) {--gap[h[pos]]; if (gap[h[pos]] == 0) {h[source] = n;} h[pos] = minh + 1;++gap[h[pos]];} return cost - lv; } int sap(int st, int ed) { source = st;sink = ed;int ret = 0;memset(gap, 0, sizeof(gap));memset(h, 0, sizeof(h)); //gap[st] = n;gap[0] = n; while (h[st] < n) {ret += dfs(st, INT_MAX);} return ret;}
0 0
- 【网络流各种模板】
- 【模板】网络流
- 网络流模板--dinic
- 网络流模板--edmondsKarp
- 网络流模板--spfa
- 网络流(模板)
- 网络流算法模板
- 网络流模板
- 网络流模板
- 网络流基础模板
- 网络流SAP模板
- 网络流模板大全
- 最大网络流 模板
- 【网络流模板】
- [模板]网络流
- 网络流模板
- 网络流模板
- 网络流模板
- 移动应用UI设计中的48dp定
- 利用servlet处理表单登录数据
- 在线编程网站
- The connection to adb is down, and a severe error has occured.
- 无法在虚拟机上安装X64操作系统的问题
- 网络流模板
- 毕设进程:postgreSQL操作入门
- 开发板串口打印信息改为显示在开发板触摸屏
- hadoop全方位资料整理
- C#出现sqlite的database is locked的解决方法
- 九度1085解题报告(机试出这种题我死定了)
- 在vs2010下使用QT
- html固定表头
- 从程序的入口了解方法