标签:
http://acm.hdu.edu.cn/showproblem.php?pid=4975
3 1 1 5 5 2 2 0 10 0 10 2 2 2 2 2 2
Case #1: So simple! Case #2: So naive! Case #3: So young!
/** hdu 4975 网络流及‘删边法’判是否为唯一流 题目大意:给定一个n*m的棋盘,给出每行的和以及每列的和,问是否可以确定出该棋盘(唯一,多解or无解) 解题思路:源点与各行建边,流量行和,汇点与各列建边,流量列和,行和列相互建边,流量9。跑网络流,满流有解; 至于判断多解,我们对残余网络进行dfs判断是否能找出边数大于2的非零环,若残余网络上有多个点构成一 个环,那么流量可在这个环上调整,某条边上多余的流量可以被环上的其他的边弥补回来。所以如果残余网 络上存在一个边数大于2的环,那么问题则是多解。 */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int oo=1e9; const int mn=1015; const int mm=505*505*3; ///=========最大流========= int node,src,dest; int ver[mm],flow[mm],nex[mm]; int head[mn],ip,work[mn],dis[mn],q[mn]; void prepare(int _node,int _src,int _dest) { node=_node,src=_src,dest=_dest; memset(head,-1,sizeof(head)); ip=0; } void addedge(int u,int v,int c) { ver[ip]=v,flow[ip]=c,nex[ip]=head[u],head[u]=ip++; ver[ip]=u,flow[ip]=0,nex[ip]=head[v],head[v]=ip++; } bool Dinic_bfs() { int i,u,v,l,r=0; for(i=0; i<node; i++)dis[i]=-1; dis[q[r++]=src]=0; for(l=0; l<r; l++) { for(i=head[u=q[l]]; i!=-1; i=nex[i]) { if(flow[i]&&dis[v=ver[i]]<0) { dis[q[r++]=v]=dis[u]+1; if(v==dest)return 1; } } } return 0; } int Dinic_dfs(int u,int exp) { if(u==dest)return exp; for(int &i=work[u],v,tmp; i>=0; i=nex[i]) { if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0) { flow[i]-=tmp; flow[i^1]+=tmp; return tmp; } } return 0; } int Dinic_flow() { int i,ret=0,delta; while(Dinic_bfs()) { for(i=0; i<node; i++)work[i]=head[i]; while(delta=Dinic_dfs(src,oo))ret+=delta; } return ret; } ///============判环============= int walked[mn]; bool dfs(int u,int pre) { int biu=-1; walked[u]=true; for(int i=head[u]; i!=-1; i=nex[i]) { int v=ver[i]; if(v==pre)continue; if(flow[i]>0) { if(walked[v])return true; if(dfs(v,u))return true; } if(biu==-1)head[u]=nex[i]; else nex[biu]=nex[i]; biu=i; } walked[u]=false; return false; } bool judge() { memset(walked,false,sizeof(walked)); for(int i=1; i<=node; i++) { if(dfs(i,-1))return true; } return false; } ///============================== int n,m,c1[mn],c2[mn]; int main() { int T,tt=0; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); int sum1=0,sum2=0; for(int i=1; i<=n; i++) { scanf("%d",&c1[i]); sum1+=c1[i]; } for(int i=1; i<=m; i++)walked[mn]; { scanf("%d",&c2[i]); sum2+=c2[i]; } printf("Case #%d: ",++tt); if(sum1!=sum2) { puts("So naive!"); continue; } ///====建边==== prepare(n+m+2,0,n+m+1); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { addedge(i,j+n,9); } } for(int i=1; i<=n; i++) { addedge(src,i,c1[i]); } for(int i=1; i<=m; i++) { addedge(i+n,dest,c2[i]); } ///============ if(Dinic_flow()!=sum1) { puts("So naive!"); } else { if(judge()) puts("So young!"); else puts("So simple!"); } } return 0; }
3 1 1 5 5 2 2 0 10 0 10 2 2 2 2 2 2
Case #1: So simple! Case #2: So naive! Case #3: So young!
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/47300391