2014-12-20 00:56:43
思路:最大流启蒙题(启蒙好晚orz....)
研究了一下Fork-Fulkerson、EK和Dinic,前两者差别就在与用DFS还是BFS来找增广路,Dinic的话采用了分层图的概念,优化了增广路多次查找过程。
总结下:(1)基于流的边反对称性、非源/汇点出入守恒、增广路定理(同理于二分匹配)三大原理(2)通过构造“反向边”的概念使得找增广路算法可以“反悔”
(3)通过不断增广来增加流量,最终达到最大流。
分别用EK、FF、Dinic实现了下。
EK:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int INF = 1 << 30; 20 const int maxn = 210; 21 22 int pre[maxn],c[maxn][maxn],n,m; 23 bool vis[maxn]; 24 queue<int> Q; 25 26 bool Bfs(){ 27 while(!Q.empty()) Q.pop(); 28 memset(vis,false,sizeof(vis)); 29 memset(pre,-1,sizeof(pre)); 30 vis[1] = true; 31 Q.push(1); 32 while(!Q.empty()){ 33 int x = Q.front(); Q.pop(); 34 for(int i = 1; i <= m; ++i) if(!vis[i] && c[x][i] > 0){ 35 pre[i] = x; 36 vis[i] = true; 37 if(i == m) return true; 38 Q.push(i); 39 } 40 } 41 return false; 42 } 43 44 int EK(){ 45 int max_flow = 0,plus; 46 while(Bfs()){ 47 plus = INF; 48 for(int i = m; i != 1; i = pre[i]) plus = min(plus,c[pre[i]][i]); 49 for(int i = m; i != 1; i = pre[i]){ 50 c[pre[i]][i] -= plus; 51 c[i][pre[i]] += plus; 52 } 53 max_flow += plus; 54 } 55 return max_flow; 56 } 57 58 int main(){ 59 int v1,v2,v3; 60 while(scanf("%d%d",&n,&m) != EOF){ 61 memset(c,0,sizeof(c)); 62 for(int i = 1; i <= n; ++i){ 63 scanf("%d%d%d",&v1,&v2,&v3); 64 c[v1][v2] += v3; 65 } 66 printf("%d\n",EK()); 67 } 68 return 0; 69 }