最簡單的最大流演算法,不斷搜尋增廣路增廣。
這是很不划算的演算法,因為效率太低了,隨便一個資料都能把它卡住。雖然現在10分鐘就能打出一個沒有錯誤的SAP,花很長時間搞出這個很不划算。但是,我不能死記一個進階的演算法而連最基礎的演算法都打不出來。競賽雖然功利,但是學習演算法也並不是完全為了競賽。
在網上找,只能找到幾個,因為搞競賽至少也要用個EK,很少有人做題用DFS的。找到的幾個,有的寫得太醜了,有的只是給出了過程,反正找不到滿意的。因為過程倒是很好理解,自己嘗試打了一下,但是調不過去。最後在http://blog.csdn.net/l344431432/article/details/5679106找到了滿意的DFS最大流演算法實現,模仿著改一下,終於調出來了。另外,這個網址對於那道題的演算法描述可能有問題,但代碼是對的。
其實DFS最大流和ISAP差不多,或者說ISAP就是它的一種改進,用距離標號來實現尋找最短增光路。而EK是廣搜,dinic是構造分層圖。代碼和ISAP的很像。而且,代碼真的很短。
另外,有時候DFS最大流並不是很差,在RQNOJ我的程式跑得比ISAP等理論複雜度更低的演算法還快,可能是常數小而且資料友好的原因吧。這個演算法還是很看RP的。
代碼:
#include <stdio.h>#define MAXN 300#define INF 19930317int c[MAXN][MAXN];int s, t, i, k, u, v, w, n, m;int flow, maxflow;int vis[MAXN];int dfs(int u, int low){ int i, flow; if (u == t) return low; if (vis[u]) return 0; vis[u] = 1; for (i = 1; i <= n; i++) if (c[u][i] && (flow = dfs(i, low < c[u][i] ? low : c[u][i]))) { c[u][i] -= flow; c[i][u] += flow; return flow; } return 0;}int main(){ scanf("%d%d", &m, &n); for (i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); c[u][v] += w; } s = 1; t = n; while (flow = dfs(s, INF)) { maxflow += flow; memset(vis, 0, sizeof(vis)); } printf("%d\n", maxflow);}
多路增廣
#include <stdio.h>#define MAXN 300#define INF 19930317int c[MAXN][MAXN];int s, t, i, k, u, v, w, n, m;int flow, maxflow;int vis[MAXN];int dfs(int u, int low){ int i, flow, sum = 0; if (u == t) return low; if (vis[u]) return 0; vis[u] = 1; for (i = 1; i <= n; i++) if (c[u][i] && (flow = dfs(i, low < c[u][i] ? low : c[u][i]))) { sum += flow; low -= flow; c[u][i] -= flow; c[i][u] += flow; if (!low) break; } return sum;}int main(){ scanf("%d%d", &m, &n); for (i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); c[u][v] += w; } s = 1; t = n; while (flow = dfs(s, INF)) { maxflow += flow; memset(vis, 0, sizeof(vis)); } printf("%d\n", maxflow);}