CF-546E. Soldier and Traveling(网络最大流)

CF传送门

洛谷传送门


解题思路

把城市拆成两个点——入点(1~n)和出点(n+1~2n),然后以下情况连边:

  • 读入的边(入连向出),边的流量为max
  • 超级源点向所有城市入点连边,流量为a[i]
  • 所有城市入点向出点连边,流量为max
  • 所有城市出点向汇点连边,流量为b[i]

跑一边最大流,若最大流结果等于b[i]的和,则可以达到目标,然后扫一遍图,输出方案。

坑点比较多:

  1. 各种数组开两倍空间
  2. edge结构体开10倍空间
  3. 建图一定要建反边
  4. cnt初始化为-1或1
  5. 判断a[i]的和与b[i]的和是否相等
  6. 最后跑图统计答案时要求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 }

 

posted @ 2021-03-07 00:33  尹昱钦  阅读(112)  评论(0编辑  收藏  举报