慢慢更...
HihoCoder上的最大流模板题:网络流二·最大流最小割定理
抄的《挑战程序设计竞赛》上的代码
#include <cstdio> #include <cmath> #include <vector> #include <algorithm> #include <queue> #include <cstring> using namespace std; const int MAX=10005; const int INF=1<<30; struct edge { int to,cap,rev; edge(int x,int y,int z) { to=x,cap=y,rev=z; } }; int s,t; vector<edge> v[MAX]; inline void add_edge(int x,int y,int cap) { v[x].push_back(edge(y,cap,v[y].size())); v[y].push_back(edge(x,0,v[x].size()-1)); } int level[MAX]; queue<int> Q; inline void bfs() { memset(level,-1,sizeof(level)); level[s]=0; Q.push(s); while(!Q.empty()) { int x=Q.front(); Q.pop(); for(int i=0;i<v[x].size();i++) { edge &e=v[x][i]; if(e.cap>0 && level[e.to]<0) { level[e.to]=level[x]+1; Q.push(e.to); } } } } int iter[MAX]; inline int dfs(int x,int f) { if(x==t) return f; for(int &i=iter[x];i<v[x].size();i++) { edge &e=v[x][i]; if(e.cap>0 && level[e.to]>level[x]) { int d=dfs(e.to,min(f,e.cap)); if(d>0) { e.cap-=d; v[e.to][e.rev].cap+=d; return d; } } } return 0; } inline int max_flow() { int flow=0; while(1) { bfs(); if(level[t]<0) break; memset(iter,0,sizeof(iter)); int f=0; while((f=dfs(s,INF))>0) flow+=f; } return flow; } int n,m; int main() { // freopen("input.txt","r",stdin); scanf("%d%d",&n,&m); s=1,t=n; for(int i=1;i<=m;i++) { int x,y,cap; scanf("%d%d%d",&x,&y,&cap); add_edge(x,y,cap); } printf("%d ",max_flow()); vector<int> cut; for(int i=1;i<=n;i++) if(level[i]>=0) cut.push_back(i); printf("%d\n",(int)cut.size()); for(int i=0;i<cut.size();i++) printf("%d ",cut[i]); return 0; }
一道挺裸的最大流:CF 456E ($Soldier$ $and$ $Traveling$)
把$a_i$、$b_i$当成两组点($1$~$n$,$n+1$~$2n$),自建源点汇点
原点向第一组连边,第二组向汇点连边,流量限制分别为$a_i$、$b_i$
两组间的连边是第一组向第二组,$m$条路径能连出$2m$条边;然后由于可以停留,又可以连出$n$条($i$到$n+i$)。流量限制都为流出点的限制
输出的是每条边(如果有的话)的流量
热身题
#include <cstdio> #include <cmath> #include <vector> #include <algorithm> #include <queue> #include <cstring> using namespace std; const int N=205; const int INF=1<<30; struct edge { int to,cap,rev; edge(int x,int y,int z) { to=x,cap=y,rev=z; } }; int s,t; vector<edge> v[N]; inline void add_edge(int x,int y,int cap) { v[x].push_back(edge(y,cap,v[y].size())); v[y].push_back(edge(x,0,v[x].size()-1)); } int level[N]; queue<int> Q; inline void bfs() { memset(level,-1,sizeof(level)); level[s]=0; Q.push(s); while(!Q.empty()) { int x=Q.front(); Q.pop(); for(int i=0;i<v[x].size();i++) { edge &e=v[x][i]; if(e.cap>0 && level[e.to]<0) { level[e.to]=level[x]+1; Q.push(e.to); } } } } int iter[N]; inline int dfs(int x,int f) { if(x==t) return f; for(int &i=iter[x];i<v[x].size();i++) { edge &e=v[x][i]; if(e.cap>0 && level[e.to]>level[x]) { int d=dfs(e.to,min(f,e.cap)); if(d>0) { e.cap-=d; v[e.to][e.rev].cap+=d; return d; } } } return 0; } inline int max_flow() { int flow=0; while(1) { bfs(); if(level[t]<0) break; memset(iter,0,sizeof(iter)); int f=0; while((f=dfs(s,INF))>0) flow+=f; } return flow; } int n,m; int a[N],b[N]; int ans[N][N]; int main() { scanf("%d%d",&n,&m); s=n*2+1,t=n*2+2; int suma=0,sumb=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]),suma+=a[i]; for(int i=1;i<=n;i++) scanf("%d",&b[i]),sumb+=b[i]; if(suma!=sumb) { printf("NO\n"); return 0; } for(int i=1;i<=n;i++) add_edge(s,i,a[i]); for(int i=1;i<=n;i++) add_edge(i,n+i,a[i]); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); add_edge(x,n+y,a[x]); add_edge(y,n+x,a[y]); } for(int i=1;i<=n;i++) add_edge(n+i,t,b[i]); if(max_flow()!=sumb) { printf("NO\n"); return 0; } printf("YES\n"); for(int i=1;i<=n;i++) for(int j=0;j<v[i].size();j++) { int to=v[i][j].to; int flow=v[to][v[i][j].rev].cap; ans[i][to-n]=flow; } for(int i=1;i<=n;i++,printf("\n")) for(int j=1;j<=n;j++) printf("%d ",ans[i][j]); return 0; }
(待续)