题目链接:click here~~
【题目大意】:给定一些城市里面原先状态的士兵数目,和某些城市之间的联通关系,求能否达到最终状态。
【解题思路】做完这套题,感觉这道题是五个题里最有质量的题了,搞了差不多一天半的时间,开始很难想到构图,想到了是最大流之后,又卡在了输出流量上,w(゚Д゚)w,还是这类题做的太少,~~~~(>_<)~~~~!首先比较很难构想到最大流,但是抓住题目关键,仔细想想也不难,好,想到了是构造最大流,那么接下来难点是建源点,汇点,剩下的就是套模板了,弱弱的献上代码,欢迎各位指正~~
Sample Input
4 4 1 2 6 3 3 5 3 1 1 2 2 3 3 4 4 2
YES 1 0 0 0 2 0 0 0 0 5 1 0 0 0 2 1
2 0 1 2 2 1
NO
代码:
/* Author :HRW 思路:建图,最大流,注意反向边,容量,流量为0 建源点,汇点, 最后输出路径保证每条边的流量都要输出,只需之前统计有哪些边流量发生了变化 */ #include <bits/stdc++.h> using namespace std; const int N=305; const int inf=0x3f3f3f3f; struct Edge { int from,to,cap,flow;//顶点-顶点,容量,流量 Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {} }; vector <Edge> edges; vector <int > G[N]; int d[N],cur[N],num[N][N]; int n,m,S,T,a,b,C; bool vis[N],flag; void init() { for(int i=0; i<=n; i++) { G[i].clear(),edges.clear(); } } void add_edge(int from,int to,int cap) { edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); C=edges.size(); G[from].push_back(C-2); G[to].push_back(C-1); } bool bfs(int s,int t) { memset(vis,false,sizeof(vis)); queue <int >Q; d[s]=0; Q.push(s); vis[s]=true; while(!Q.empty()) { int q=Q.front(); Q.pop(); for(int i=0; i<G[q].size(); i++)//一定要注意G[q].size(),写成G[i].size(),样例竟然过,导致RE一页! { Edge &e=edges[G[q][i]]; if(!vis[e.to]&&e.cap>e.flow) { d[e.to]=d[q]+1; Q.push(e.to); vis[e.to]=true; } } } return vis[T]; } int dfs(int s,int k) { if(s==T||k==0) return k; int f,flow=0; for(int &i=cur[s]; i<G[s].size(); i++) { Edge &e=edges[G[s][i]]; if(d[e.to]==d[s]+1&&(f=dfs(e.to,min(k,e.cap-e.flow)))>0) { e.flow+=f; edges[G[s][i]^1].flow-=f; flow+=f; k-=f; if(k==0) break; } } return flow; } int max_flow(int s,int t) { int flow=0; while(bfs(s,t)) { memset(cur,0,sizeof(cur)); flow+=dfs(s,inf); } return flow; } int main() { init(); scanf("%d%d",&n,&m); S=0,T=2*n+1; int u,v,a,b,suma=0,sumb=0; for(int i=1; i<=n; i++) { scanf("%d",&a); suma+=a; add_edge(S,i,a); add_edge(i,i+n,inf); } for(int i=1; i<=n; i++) { scanf("%d",&b); sumb+=b; add_edge(i+n,T,b); } if(suma!=sumb) { puts("NO"); return 0; } while(m--) { scanf("%d%d",&v,&u); add_edge(v,u+n,inf); add_edge(u,v+n,inf); } int ans=max_flow(S,T); //cout<<ans<<endl; if(suma!=ans) { puts("NO"); } else { puts("YES"); for(int i=1; i<=n; i++) { for(int j=0; j<G[i].size(); j++) { Edge&e=edges[G[i][j]]; if(e.to>0) num[i][e.to-n]=e.flow; } } for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) printf("%d ",num[i][j]); puts(""); } } return 0; } /* 4 4 1 2 6 3 3 5 3 1 1 2 2 3 3 4 4 2 */