板子 网络流算法
1 .Edmonds-Karp 算法 : 通过反向增光路+bfs 求解最大流
#include<bits/stdc++.h> using namespace std; #define LOACL freopen("in","r",stdin);\ freopen("out","w",stdout); #define FASTIO ios::sync_with_stdio(false); #define CLOCK cout<<1.*clock()/CLOCKS_PER_SEC<<"ms"<<"\n"; #define add(u,v,w) e[++tot]=(edge){v,head[u],1},head[u]=tot; #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define DBG(x) cout<<(#x)<<"="<<x<<endl #define DBG2(x,y) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<endl #define DBG3(x,y,z) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<"\t"<<(#z)<<"="<<z<<endl #define FOR(i, a, b) for(int i=(a); i<(b); i++) #define REP(i, a, b) for(int i=(a); i<=(b); i++) #define DOWN(i, a, b) for(int i=(a); i>=(b); i--) #define Loop(i,u) for(int i =head[u];i;i=e[i].nxt) #define all(x) x.begin(),x.end() #define low(x) (x)&(-x) #define pb push_back typedef long long ll; typedef double dl; const int sz = 222; const int inf = 0x3ffffff; int m, n, x, y, z, g[sz][sz], pre[sz], flow[sz], maxflow; queue<int>q ; #if 1 int bfs(int s, int t) { while (!q.empty()) q.pop(); REP(i, 1, n) pre[i] = -1; pre[s] = 0; flow[s] = inf; q.push(s); while (!q.empty()) { int x = q.front() ; q.pop(); if (x == t)break; REP(i, 1, n) { if (g[x][i] > 0 && pre[i] == -1) { pre[i] = x; flow[i] = min(flow[x], g[x][i]); q.push(i); } } } if (pre[t] == -1) return -1; else return flow[t]; } #endif void EK(int s, int t) { int increase = 0; while ( (increase = bfs(s, t)) != -1) { int k = t; while (k != s) { int last = pre[k]; g[last][k] -= increase; g[k][last] += increase; k = last; } maxflow += increase; } } int main() { LOACL cin >> m >> n; REP(i, 1, m) { cin >> x >> y >> z; g[x][y] += z; } EK(1, n); cout << maxflow; }
2Dinic 算法 BFS 分层 DFS 找最大流
#include<bits/stdc++.h> using namespace std; #define LOACL freopen("in","r",stdin);\ freopen("out","w",stdout); #define FASTIO ios::sync_with_stdio(false); #define CLOCK cout<<1.*clock()/CLOCKS_PER_SEC<<"ms"<<"\n"; const int inf = 987654321; const int sz = (int)100010; const int mod = (int)1e9 + 7; const int sqrtn = 300; #define add(u,v,w) e[++tot]=(edge){v,head[u],w},head[u]=tot; #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define DBG(x) cout<<(#x)<<"="<<x<<endl #define DBG2(x,y) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<endl #define DBG3(x,y,z) cout<<(#x)<<"="<<x<<"\t"<<(#y)<<"="<<y<<"\t"<<(#z)<<"="<<z<<endl #define FOR(i, a, b) for(int i=(a); i<(b); i++) #define REP(i, a, b) for(int i=(a); i<=(b); i++) #define DOWN(i, a, b) for(int i=(a); i>=(b); i--) #define Loop(i,u) for(int i =head[u];i;i=e[i].nxt) #define all(x) x.begin(),x.end() #define low(x) (x)&(-x) #define pb push_back typedef long long ll; typedef double dl; struct edge { int v,nxt,w; }e[sz<<1]; int head[sz],tot=-1,level[sz]; int n,m,s,t,u,v,w; int bfs(int s,int t) { CLR(level,0); level[s]=1; queue<int>q ; q.push(s); while(!q.empty()) { int v =q.front();q.pop(); Loop(i,v) { if(e[i].w> 0 &&!level[e[i].v]) { level[e[i].v]=level[v]+1; q.push(e[i].v); } } } return level[t]; } int dfs(int v,int t,int f) { if(v==t) return f; int add =0 ; Loop(i,v) { if(e[i].w> 0 && level[v]+1==level[e[i].v]) { int d =dfs(e[i].v,t,min(f-add,e[i].w)); if(d>0) { e[i].w-=d; e[i^1].w+=d; add+=d; } else level[e[i].v] =-1; } if(add>=f)break; } return add; } int Dinic(int s,int t) { int flow = 0; while(bfs(s,t)) flow+=dfs(s,t,0x3f3f3f3f); return flow; } int main() { LOACL cin>>n>>m>>s>>t; REP(i,1,m) { cin>>u>>v>>w; add(u,v,w);add(v,w,0); } cout<<Dinic(s,t); }
费用流 EK算法 spfa 找增广路 + 尾部合并
#include<bits/stdc++.h> using namespace std; #define LOACL freopen("in","r",stdin);\ freopen("out","w",stdout); const int sz = 50010; const int inf = 0x3f3f3f3f; #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define REP(i, a, b) for(int i=(a); i<=(b); i++) #define Loop(i,u) for(int i = head[u];i!=-1;i=e[i].nxt) int n, m, s, t, u, v, w, f; struct edge { int v, nxt, w, f; } e[sz << 1]; int tot = -1, head[sz], pre[sz], inq[sz], dist[sz], incf[sz], maxflow, ans; void add(int u, int v, int w, int f) { e[++tot] = (edge) {v, head[u], w, f}, head[u] = tot; } bool spfa(int s, int t) { fill(dist, dist + n + 1, INT_MAX); CLR(inq, 0); queue<int>q ; q.push(s); inq[s] = 1; dist[s] = 0; incf[s] = inf; while(!q.empty()) { int v = q.front();q.pop(); inq[v]=0; Loop(i,v) { if(e[i].w>0 && dist[e[i].v]>dist[v]+e[i].f) { dist[e[i].v]=dist[v]+e[i].f; incf[e[i].v]=min(e[i].w,incf[v]); pre[e[i].v]=i; if(!inq[e[i].v]) { q.push(e[i].v); inq[e[i].v]=1; } } } } return dist[t]!=INT_MAX; } void update(int s, int t) { int x = t; while (x != s) { int i = pre[x]; e[i].w -= incf[t]; e[i ^ 1].w += incf[t]; x = e[i ^ 1].v; } maxflow += incf[t]; ans += dist[t] * incf[t]; } void EK(int s, int t) { while (spfa(s, t)) update(s, t); } int main() { LOACL CLR(head,-1); cin >> n >> m >> s >> t; REP(i, 1, m) { cin >> u >> v >> w >> f; add(u, v, w, f); add(v, u, 0, -f); } EK(s, t); cout << maxflow << " " << ans << endl; }
不摸着石头过河,难道要在温柔乡睡到天昏地暗。