hdu4975:http://acm.hdu.edu.cn/showproblem.php?pid=4975
题意:给你一个n*m的矩阵,矩阵中的元素都是0--9,现在给你这个矩阵的每一行和每一列的和,问你这个矩阵是否存在,唯一,或者不唯一。
题解:这一题就是用传说中的网络流破解。首先建图就是把每一行和每一列看成一个点,行和源点建立一条边,容量为这一行的和,列和汇点建边,容量是这一列的和,然后每一行和每一列建立一边,容量是9.然后跑网络流,如果流量和总和相等,说明有解,然后用判断是否唯一,题解中就是说要判断是否存在环,这里用到了类似tarjan的方法判断是否有环。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<queue> 6 #define INF 100000000 7 using namespace std; 8 const int N=3005; 9 const int M=2000000; 10 struct Node{ 11 int v; 12 int f; 13 int next; 14 }edge[M]; 15 int n,m,u,v,cnt,sx,ex; 16 int head[N],pre[N]; 17 bool vis[N],no[N]; 18 int st[N],top;//根据题目要求申请 19 void init(){ 20 cnt=0; 21 memset(head,-1,sizeof(head)); 22 memset(vis,0,sizeof(vis)); 23 memset(no,0,sizeof(no)); 24 } 25 void add(int u,int v,int w){ 26 edge[cnt].v=v; 27 edge[cnt].f=w; 28 edge[cnt].next=head[u]; 29 head[u]=cnt++; 30 edge[cnt].f=0; 31 edge[cnt].v=u; 32 edge[cnt].next=head[v]; 33 head[v]=cnt++; 34 } 35 bool BFS(){ 36 memset(pre,0,sizeof(pre)); 37 pre[sx]=1; 38 queue<int>Q; 39 Q.push(sx); 40 while(!Q.empty()){ 41 int d=Q.front(); 42 Q.pop(); 43 for(int i=head[d];i!=-1;i=edge[i].next ){ 44 if(edge[i].f&&!pre[edge[i].v]){ 45 pre[edge[i].v]=pre[d]+1; 46 Q.push(edge[i].v); 47 } 48 } 49 } 50 return pre[ex]>0; 51 } 52 int dinic(int flow,int ps){ 53 int f=flow; 54 if(ps==ex)return f; 55 for(int i=head[ps];i!=-1;i=edge[i].next){ 56 if(edge[i].f&&pre[edge[i].v]==pre[ps]+1){ 57 int a=edge[i].f; 58 int t=dinic(min(a,flow),edge[i].v); 59 edge[i].f-=t; 60 edge[i^1].f+=t; 61 flow-=t; 62 if(flow<=0)break; 63 } 64 } 65 if(f-flow<=0)pre[ps]=-1; 66 return f-flow; 67 } 68 int solve(){ 69 int sum=0; 70 while(BFS()) 71 sum+=dinic(INF,sx); 72 return sum; 73 } 74 bool dfs(int u,int pre,bool flag){ 75 vis[u] = 1; 76 st[top++] = u; 77 for(int i = head[u];i != -1;i = edge[i].next){ 78 int v = edge[i].v; 79 if(edge[i].f<=0)continue; 80 if(v == pre)continue; 81 if(!vis[v]){ 82 if(dfs(v,u,edge[i^1].f >0))return true; 83 } 84 else if(!no[v])return true; 85 } 86 if(!flag){ 87 while(1){ 88 int v = st[--top]; 89 no[v] = true; 90 if(v == u)break; 91 } 92 } 93 return false; 94 } 95 int main(){ 96 int T,sumc,sumr,ans,temp,tt=1; 97 scanf("%d",&T); 98 while(T--){ 99 scanf("%d%d",&n,&m); 100 init(); 101 ans=1,sumc=sumr=0;sx=0;ex=n+m+1; 102 for(int i=1;i<=n;i++){ 103 scanf("%d",&temp); 104 add(sx,i,temp); 105 sumr+=temp; 106 for(int j=1;j<=m;j++) 107 add(i,j+n,9); 108 } 109 for(int i=1;i<=m;i++){ 110 scanf("%d",&temp); 111 add(i+n,ex,temp); 112 sumc+=temp; 113 } 114 top=0; 115 if(sumr!=sumc){ 116 ans=0; 117 } 118 else if(sumr!=solve()){ 119 ans=0; 120 } 121 else if(dfs(n+m+1,n+m+1,0)){ 122 ans=2; 123 } 124 if(ans==0) 125 printf("Case #%d: So naive! ",tt++); 126 else if(ans==1) 127 printf("Case #%d: So simple! ",tt++); 128 else 129 printf("Case #%d: So young! ",tt++); 130 } 131 }