codeforces 546E Soldier and Traveling 网络流
题目大意:有n座城市,每座城市都有一些初始的士兵$Ai$,每个士兵只能通过一条路径达到相邻的城市,然后问能否使得第i座城市的士兵数量是$Bi$,如果可以,要输出流动的方案。
思路:如果不需要输出流动的方案,那么就是个简单的网络流模板题了,而考虑上输出方案,则需要把一个点拆成$i$和$n+i$,建立$(S,i,a[i]),(i,i+n,inf),(i+n,T,b[i])$三条边,对于一条路径(u,v),则建立$(u,v+n,inf),(v,u+n,inf)$两条边,然后跑最大流,判断最后的流和和b数组的和是否相等则可以得到合法性。
对于输出路径,则要遍历u的每一条边,如果终点v大于n,则将这条边的反向边流量带入答案。这里就体现了拆点的意义,能将反向边和初始的边区别开来。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll INFLL = 0x3f3f3f3f3f3f3f3f; const int INF = 0x3f3f3f3f; const int maxn = 1e6 + 10; struct Edge { int to, flow, nxt; Edge() {} Edge(int to, int nxt, int flow):to(to),nxt(nxt), flow(flow) {} } edge[maxn << 2]; int head[maxn], dep[maxn]; int S, T; int N, n, m, tot; int mp[110][110]; void init(int n) { N = n; for (int i = 0; i <= N; ++i) head[i] = -1; tot = 0; } void addv(int u, int v, int w, int rw = 0) { edge[tot] = Edge(v, head[u], w); head[u] = tot++; edge[tot] = Edge(u, head[v], rw); head[v] = tot++; } bool BFS() { for (int i = 0; i < N; ++i) dep[i] = -1; queue<int>q; q.push(S); dep[S] = 1; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; ~i; i = edge[i].nxt) { if (edge[i].flow && dep[edge[i].to] == -1) { dep[edge[i].to] = dep[u] + 1; q.push(edge[i].to); } } } return dep[T] < 0 ? 0 : 1; } int DFS(int u, int f) { if (u == T || f == 0) return f; int w, used = 0; for (int i = head[u]; ~i; i = edge[i].nxt) { if (edge[i].flow && dep[edge[i].to] == dep[u] + 1) { w = DFS(edge[i].to, min(f - used, edge[i].flow)); edge[i].flow -= w; edge[i ^ 1].flow += w; used += w; if (used == f) return f; } } if (!used) dep[u] = -1; return used; } int Dicnic() { int ans = 0; while (BFS()) { ans += DFS(S, INF); } return ans; } int main() { while(cin>>n>>m) { init(2*n+2); S=0,T=2*n+1; int sum=0,ans=0; for(int i=1;i<=n;i++) { int x; scanf("%d",&x); addv(S,i,x); addv(i,i+n,INF); sum+=x; } for(int i=1;i<=n;i++) { int x; scanf("%d",&x); addv(i+n,T,x); ans+=x; } while(m--) { int u,v; scanf("%d%d",&u,&v); addv(u,v+n,INF); addv(v,u+n,INF); } if(ans!=sum){ printf("NO\n"); continue; } ans=Dicnic(); if(ans!=sum){ printf("NO\n"); continue; }else puts("YES"); for(int u=1;u<=n;u++) { for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v>n){ mp[u][v-n]=edge[i^1].flow; } } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { printf("%d%c",mp[i][j]," \n"[j==n]); } } } }
——愿为泰山而不骄
qq850874665~~