网络流
最大流:
详情搜索,
算法:Dinic ISAP 预流推进算法;
Dinic模板:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<cstdlib> 6 #include<queue> 7 using namespace std; 8 const int maxn = 10101; 9 10 struct Edge 11 { 12 int from,to,cap,flow; 13 Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow) 14 {} 15 }; 16 17 struct Dinic{ 18 vector<Edge> edges; 19 vector<int> G[maxn]; 20 int cur[maxn]; 21 int vis[maxn]; 22 int d[maxn]; 23 int s;int t; 24 static const int INF = 1<<29; 25 26 void AddEdge(int from,int to,int cap) 27 { 28 edges.push_back(Edge(from,to,cap,0)); 29 edges.push_back(Edge(to,from,0,0)); 30 int m = edges.size(); 31 G[from].push_back(m-2); 32 G[to].push_back(m-1); 33 } 34 35 36 bool bfs() 37 { 38 memset(vis,0,sizeof(vis)); 39 queue<int> Q; 40 Q.push(s); 41 d[s] = 0; 42 vis[s] = 1; 43 while(!Q.empty()) 44 { 45 int u = Q.front();Q.pop(); 46 for(int i = 0;i < G[u].size();i++) 47 { 48 Edge& e = edges[G[u][i]]; 49 if(!vis[e.to]&&e.cap > e.flow ) 50 { 51 d[e.to] = d[u] +1; 52 vis[e.to] = 1; 53 Q.push(e.to); 54 } 55 } 56 } 57 return vis[t]; 58 } 59 60 int dfs(int now,int a) 61 { 62 if(now == t||a == 0) return a; 63 int flow = 0,f; 64 for(int& i = cur[now];i < G[now].size();i++) 65 { 66 Edge& e = edges[G[now][i]]; 67 if(d[e.to] == d[now] + 1&&(f = (dfs(e.to,min(a,e.cap-e.flow)))) > 0) 68 { 69 flow += f; 70 e.flow += f; 71 edges[G[now][i]^1].flow -= f; 72 a -= f; 73 74 if(a == 0) break; 75 } 76 } 77 return flow; 78 } 79 80 int MaxFlow(int s,int t) 81 { 82 this->s = s;this -> t = t; 83 int flow = 0; 84 while(bfs()) 85 { 86 memset(cur,0,sizeof(cur)); 87 flow += dfs(s,INF); 88 } 89 return flow; 90 } 91 }solver; 92 93 94 int main() 95 { 96 int n,m; 97 scanf("%d%d",&n,&m); 98 for(int i = 0;i < n;i++) 99 { 100 int from,to,cap; 101 scanf("%d%d%d",&from,&to,&cap); 102 solver.AddEdge(from,to,cap); 103 } 104 cout<<solver.MaxFlow(1,m)<<endl; 105 106 107 return 0; 108 }
Dinic优点,容易理解+思路明晰。不断用BFS构造分层图,再用DFS找阻塞流增广。正常O(n2m)容量都为1的话。渐进时间为Ο(min(n2/3,m1/2)m),二分图则是O(n1/2m);
附带一个板子题 codevs 1993
二分图最大匹配:飞行员配对方案问题
简单的设置下超级源和超级汇就好;傻逼错误:每次加边都加连源点和起点,重点和汇点,导致超多的重边,导致百分百全部匹配上,格外连一下就搞定,我这还调试了30分钟,实乃傻逼也。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 #include<algorithm> 6 #include<stack> 7 #include<queue> 8 #include<cstdlib> 9 10 using namespace std; 11 const int maxn = 5010; 12 const int INF = 1<<29; 13 14 struct Edge{ 15 int from,to,cap,flow; 16 Edge(int from,int to,int cap,int flow): 17 from(from),to(to),cap(cap),flow(flow){} 18 }; 19 20 struct Dinic 21 { 22 int s,t; 23 vector<Edge> edges; 24 vector<int> G[maxn]; 25 int Link[maxn]; 26 int d[maxn]; 27 int vis[maxn]; 28 int cur[maxn]; 29 30 int AddEdge(int from,int to,int cap) 31 { 32 edges.push_back(Edge(from,to,cap,0)); 33 edges.push_back(Edge(to,from,0,0)); 34 int m = edges.size(); 35 G[from].push_back(m-2); 36 G[to].push_back(m-1); 37 } 38 39 bool bfs() 40 { 41 memset(vis,0,sizeof(vis)); 42 queue<int> Q; 43 memset(d,0,sizeof(d)); 44 d[s] = 0; 45 vis[s] = 1; 46 Q.push(s); 47 while(!Q.empty()) 48 { 49 int u = Q.front();Q.pop(); 50 for(int i = 0;i < G[u].size();i++) 51 { 52 Edge& e = edges[G[u][i]]; 53 if(!vis[e.to] && e.cap > e.flow) 54 { 55 vis[e.to] = 1; 56 d[e.to] = d[u] +1; 57 Q.push(e.to); 58 } 59 } 60 } 61 return vis[t]; 62 } 63 64 int dfs(int now,int a) 65 { 66 if(now == t|| a== 0) return a; 67 int flow = 0,f; 68 for(int& i = cur[now];i < G[now].size();i++) 69 { 70 Edge& e = edges[G[now][i]]; 71 if(d[e.to] == d[now] + 1&& (f = dfs(e.to,min(a,e.cap - e.flow))) > 0 ) 72 { 73 Link[e.from] = e.to; 74 flow += f; 75 a -= f; 76 e.flow += f; 77 edges[G[now][i]^1].flow -= f; 78 if(a == 0) break; 79 } 80 } 81 return flow; 82 } 83 84 int MaxFlow(int s,int t) 85 { 86 this-> s = s;this -> t = t; 87 int flow = 0; 88 while(bfs()) 89 { 90 memset(cur,0,sizeof(cur)); 91 flow += dfs(s,1); 92 } 93 return flow; 94 } 95 96 void print(int n) 97 { 98 for(int i = 1;i <= n;i++) 99 if(Link[i]) 100 printf("%d %d\n",i,Link[i]); 101 } 102 }solver; 103 104 105 int main() 106 { 107 int n,m; 108 scanf("%d%d",&n,&m); 109 for(int i = 1;i <= n;i++) solver.AddEdge(0,i,1); 110 for(int i = n+1;i<= m;i++) solver.AddEdge(i,m+1,1); 111 int from,to; 112 while(scanf("%d%d",&from,&to) == 2&&from != -1&&to != -1) 113 { 114 solver.AddEdge(from,to,1); 115 } 116 int flow = solver.MaxFlow(0,m+1); 117 cout<<flow<<endl; 118 solver.print(n); 119 return 0; 120 }

浙公网安备 33010602011771号