感谢YB大神的总结.
以HDU1532为例的Ford_Fulkerson算法
#include <cstdio> #include <iostream> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> using namespace std; const int inf = 0x3f; const int INF = 0x3f3f3f3f; const int maxn = 1005; struct Node { int to, flow, next; }edge[maxn * maxn]; int n, m; //顶点数, 边数 int S, T; //源点, 汇点 int tot; //记录邻接表边数 int s[maxn];//DFS保存 结点的 栈 int pre[maxn], rec[maxn], mins[maxn], head[maxn]; void Add_edge(int a, int b, int c) { edge[tot].to = b; edge[tot].flow = c; edge[tot].next = head[a]; head[a] = tot++; edge[tot].to = a; edge[tot].flow = 0; edge[tot].next = head[b]; head[b] = tot++; } void Init() { tot = 0; memset(head, -1, sizeof(head)); } inline int DFS() { int top = 1; memset(pre, -1, sizeof(pre)); s[top] = S; pre[S] = S; mins[S] = INF; while(top) { int v = s[top--]; for(int i = head[v]; i != -1; i = edge[i].next) { int u = edge[i].to; if(pre[u] == -1 && edge[i].flow > 0) { pre[u] = v; rec[u] = i; mins[u] = min(mins[v], edge[i].flow); s[++top] = u; } } if(pre[T] != -1) //直到找到了汇点 return mins[T];//每次返回增广路径中容量最小的 } return -1; // 不存在增广路径 } int Ford_Fulkerson() { int add, Maxflow = 0; while((add = DFS()) != -1) {//算法知道无法找到增广路径才停止 Maxflow += add; for(int i = T; i != S; i = pre[i]) //修改残余网络 { edge[rec[i]].flow -= add; //正向减去流量 edge[rec[i]^1].flow += add;//反向增加流量 } } return Maxflow; } int main() { while(~scanf("%d %d", &n, &m)) { int i, j, k, s, e, c; Init(); for(int i = 0; i < n; i++) { cin >> s >> e >> c; Add_edge(s, e, c); } S = 1; T = m; cout << Ford_Fulkerson() << endl; } return 0; }
下面是Edmonds-Karp算法代码的实现,bfs使得找到的增广路节点数最少,和上面dfs版本代码的唯一不同就是把保存节点的栈改成了队列:
#include <cstdio> #include <iostream> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> using namespace std; const int inf = 0x3f; const int INF = 0x3f3f3f3f; const int maxn = 1005; struct Node { int to, flow, next; }edge[maxn * maxn]; int n, m; //顶点数, 边数 int S, T; //源点, 汇点 int tot; //记录邻接表边数 int q[maxn];//DFS保存 结点的 栈 int pre[maxn], rec[maxn], mins[maxn], head[maxn]; void Add_edge(int a, int b, int c) { edge[tot].to = b; edge[tot].flow = c; edge[tot].next = head[a]; head[a] = tot++; edge[tot].to = a; edge[tot].flow = 0; edge[tot].next = head[b]; head[b] = tot++; } void Init() { tot = 0; memset(head, -1, sizeof(head)); } inline int bfs() //bfs寻找增广路 { int h,t; h=t=0; memset(pre,-1,sizeof(pre)); q[h]=S; pre[S]=S; mins[S]=INF; while(h<=t) { int v=q[h++]; for(int i=head[v];i!=-1;i=edge[i].next) { int u=edge[i].to; if(pre[u]==-1 && edge[i].flow>0) { pre[u]=v; rec[u]=i; mins[u]=min(mins[v],edge[i].flow); q[++t]=u; } } if(pre[T]!=-1) //直到找到了汇点T return mins[T];//每次返回增广路径中,容量最小的值 } return -1; // 不存在增广路径 } int Edmonds_Karp() { int add,Maxflow=0; while((add=bfs())!=-1) //算法直到无法找到增广路径时才停止 { Maxflow+=add; for(int i=T;i!=S;i=pre[i]) //修改残留网络 { edge[rec[i]].flow-=add; //正向减去流量 edge[rec[i]^1].flow+=add;//反向增加流量 } } return Maxflow; } int main() { while(~scanf("%d %d", &n, &m)) { int i, j, k, s, e, c; Init(); for(int i = 0; i < n; i++) { cin >> s >> e >> c; Add_edge(s, e, c); } S = 1; T = m; cout << Edmonds_Karp() << endl; } return 0; }