CodeForces

题目链接https://codeforces.com/problemset/problem/546/E

最大流最难的就是建图了感觉,还有得看出这能是个最大流。当然这题还得输出过程  我******

题目大意:告诉你哪些点是连着的并告诉你这个点一开时有多少人,然后每人可以都可以不动或者走到相邻的点,

给出末状态问你是否可能达到,如果可以类似要输出路径。

题目思路:这题建图感觉还行,源点到各个点的值为初始,各个点(另开一组对应本来1-4 对应5-8)到汇点的值为末状态,别忘连本点即1-5,2-6。

也就是求最大流是否和末状态加起来相同。找路径正向边因为在找增广路在减也就是要找反向边的值就行了。

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 typedef long long ll;
  5 const int maxn = 1e5 + 10;
  6 const int inf = 0x3f3f3f3f;
  7 int dir[10][10] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
  8 
  9 int head[maxn], depth[maxn], cur[maxn], f[1010][1010];
 10 int cnt=1, x, y, ta, tb, ans, s, t, id, n, m,
 11 
 12 struct st
 13 {
 14     int to, next, w;
 15 }e[maxn];
 16 
 17 void add(int u, int v, int w) // cnt从2开始,从1开始错了也不知道被卡了哪里
 18 {
 19     e[++cnt].to = v;
 20     e[cnt].next = head[u];
 21     e[cnt].w = w;
 22     head[u] = cnt;
 23 }
 24 
 25 int bfs()
 26 {
 27     queue<int> q;
 28     memset(depth,0,sizeof(depth));
 29     depth[s] = 1;
 30     q.push(s);
 31     while(!q.empty())
 32     {
 33         int x = q.front(); q.pop();
 34         
 35         for(int i = head[x]; i; i = e[i].next)
 36         {
 37             int v = e[i].to;
 38             if(depth[v] == 0 && e[i].w > 0)
 39             {
 40                 depth[v] = depth[x] + 1;
 41                 q.push(v);
 42             }
 43             
 44         }
 45         
 46     }
 47     
 48     if(depth[t] > 0) return 1;
 49     else return 0;
 50 }
 51 
 52 int dfs(int u, int flow) // 内含多路增广优化
 53 {
 54     if(u == t) return flow;
 55     int ret = 0;
 56     
 57     for(int i = head[u]; i; i = e[i].next)
 58     {
 59         int v = e[i].to;
 60         if(depth[v] == depth[u] + 1 && e[i].w)
 61         {
 62             int id = dfs(v, min(e[i].w, flow - ret));
 63             ret += id; e[i].w -= id; e[i ^ 1].w += id;
 64             if(flow - ret == 0) break;
 65         }
 66         
 67     }
 68     
 69     if(!ret) depth[u] = -1; // 炸点优化
 70     return ret;
 71 }
 72 
 73 int dinic()
 74 {
 75     int ans = 0;
 76     while(bfs())
 77     {
 78         ans += dfs(s, inf);
 79     }
 80     return ans;
 81 }
 82 
 83 int main()
 84 {
 85     std::ios::sync_with_stdio(false);std::cin.tie(0);
 86     cin>>n>>m;
 87     s = 0; t = 2 * n + 1;
 88     for(int i = 1; i <= n; ++i)
 89     {
 90         cin>>x;
 91         add(s, i, x); add(i, s, 0); ta += x; 
 92     }
 93     
 94     for(int i = 1; i <= n; ++i)
 95     {
 96         cin>>x;
 97         add(i + n, t, x); add(t, i + n, 0); tb += x;
 98     }
 99     
100     for(int i = 1; i <= n; ++i)
101     {
102         add(i, i + n, inf); add(i + n, i, 0);
103     }
104     
105     for(int i = 1; i <= m; ++i)
106     {
107         cin>>x>>y;
108         add(x, y + n, inf); add(y + n, x, 0);
109         add(y, x + n, inf); add(x + n, y, 0);
110     }
111 
112     ans = dinic();
113     if(ans == tb && ta == tb)
114     {
115         cout<<"YES"<<endl;
116         for(int i = 1; i <= n; ++i)
117         {
118             for(int j = head[i]; j; j = e[j].next)
119             {
120                 int v = e[j].to;
121                 if(v > n) f[i][v - n] = e[j ^ 1].w;
122             }
123         }
124         
125         for(int i = 1; i <= n; ++i)
126         {
127             for(int j = 1; j <= n; ++j)
128             {
129                 cout<<f[i][j]<<' ';
130             }
131             cout<<endl;
132         }
133     }
134     
135     else cout<<"NO"<<endl;
136     
137     return 0;
138 }

这题只用了dinic的两个优化,还有个弧优化在其他篇里有。

原文地址:https://www.cnblogs.com/a1484755603/p/13503518.html