CF-546E. Soldier and Traveling(网络最大流)
CF传送门
洛谷传送门
解题思路
把城市拆成两个点——入点(1~n)和出点(n+1~2n),然后以下情况连边:
- 读入的边(入连向出),边的流量为max
- 超级源点向所有城市入点连边,流量为a[i]
- 所有城市入点向出点连边,流量为max
- 所有城市出点向汇点连边,流量为b[i]
跑一边最大流,若最大流结果等于b[i]的和,则可以达到目标,然后扫一遍图,输出方案。
坑点比较多:
- 各种数组开两倍空间
- edge结构体开10倍空间
- 建图一定要建反边
- cnt初始化为-1或1
- 判断a[i]的和与b[i]的和是否相等
- 最后跑图统计答案时要求e[i].v必须在n+1~2n之间才是答案
AC代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<iomanip> 12 #include<ctime> 13 #include<stack> 14 using namespace std; 15 const int maxn=205; 16 const int maxx=0x3f3f3f3f; 17 int n,m,s,t,a[maxn],b[maxn],p[201],cnt=-1,dis[205],vis[205],cur[205],ans,mp[maxn][maxn],anss; 18 struct node{ 19 int v,cap,flow,next; 20 }e[2005]; 21 void insert(int u,int v,int cap,int flow){ 22 cnt++; 23 e[cnt].v=v; 24 e[cnt].cap=cap; 25 e[cnt].flow=flow; 26 e[cnt].next=p[u]; 27 p[u]=cnt; 28 } 29 bool bfs(){ 30 queue<int> q; 31 memset(dis,-1,sizeof(dis)); 32 q.push(s); 33 dis[s]=0; 34 while(!q.empty()){ 35 int u=q.front(); 36 q.pop(); 37 for(int i=p[u];i!=-1;i=e[i].next){ 38 int v=e[i].v; 39 if(dis[v]==-1&&e[i].cap>e[i].flow){ 40 dis[v]=dis[u]+1; 41 q.push(v); 42 } 43 } 44 } 45 if(dis[t]==-1) return false; 46 else return true; 47 } 48 long long dfs(int u,int maxflow){ 49 if(u==t||maxflow==0) return maxflow; 50 long long flow=0; 51 for(int &i=cur[u];i!=-1;i=e[i].next){ 52 int v=e[i].v; 53 if(dis[v]==dis[u]+1){ 54 long long f=dfs(v,min(maxflow,e[i].cap-e[i].flow)); 55 e[i].flow+=f; 56 e[i^1].flow-=f; 57 flow+=f; 58 maxflow-=f; 59 if(maxflow==0) break; 60 } 61 } 62 return flow; 63 } 64 long long dinic(){ 65 long long fl=0; 66 while(bfs()){ 67 for(int i=0;i<=2*n+1;i++) cur[i]=p[i]; 68 fl+=dfs(s,maxx); 69 } 70 return fl; 71 } 72 int main() 73 { 74 memset(p,-1,sizeof(p)); 75 cin>>n>>m; 76 s=0; 77 t=2*n+1; 78 for(int i=1;i<=n;i++){ 79 cin>>a[i]; 80 anss+=a[i]; 81 insert(s,i,a[i],0); 82 insert(i,s,0,0); 83 insert(i,i+n,maxx,0); 84 insert(i+n,i,0,0); 85 } 86 for(int i=1;i<=n;i++){ 87 cin>>b[i]; 88 ans+=b[i]; 89 insert(n+i,t,b[i],0); 90 insert(t,n+i,0,0); 91 } 92 if(ans!=anss){ 93 cout<<"NO"; 94 return 0; 95 } 96 for(int i=1;i<=m;i++){ 97 int u,v; 98 cin>>u>>v; 99 insert(u,v+n,maxx,0); 100 insert(v+n,u,0,0); 101 insert(v,u+n,maxx,0); 102 insert(u+n,v,0,0); 103 } 104 if(dinic()!=ans) cout<<"NO"; 105 else{ 106 cout<<"YES\n"; 107 for(int u=1;u<=n;u++){ 108 for(int i=p[u];i!=-1;i=e[i].next){ 109 if((e[i].v>n&&e[i].v<=n+n)&&e[i].flow) mp[u][e[i].v-n]=e[i].flow; 110 } 111 } 112 for(int i=1;i<=n;i++){ 113 for(int j=1;j<=n;j++){ 114 cout<<mp[i][j]<<" "; 115 } 116 cout<<endl; 117 } 118 } 119 return 0; 120 }