Description
Input
Output
Sample Input
3 1 1 5 5 2 2 0 10 0 10 2 2 2 2 2 2
Sample Output
Case #1: So simple! Case #2: So naive!Case #3: So young!
题意:t组数据,然后一个n*m的矩阵,每个单元有一个0-9的整数,但是现在只告诉你:第一行n个数,告诉你每行的和,第二行m个数高数你每列的和;问这样的矩阵是否存在,如果存在是否唯一;
建立起点与汇点,起点与行和相连,列和与终点相连,行与列之间建边权值为9,判断是否满流,不满流则无法得到这样的矩阵,如果满流,利用残余网络判断是否有环,如果有,则有多种方法,否则只有一种;
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int MAXN=1100,maxn=1110; const int MAXM=503*503*3; const int INF=0x3f3f3f3f; struct Node { int to,next,cap; } edge[MAXM]; int tol; int head[MAXN]; int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN]; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw=0) { edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v]; head[v]=tol++; } int sap(int start,int end,int nodenum) { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); memcpy(cur,head,sizeof(head)); int u=pre[start]=start,maxflow=0,aug=-1; gap[0]=nodenum; while(dis[start]<nodenum) { loop: for(int &i=cur[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if(edge[i].cap&&dis[u]==dis[v]+1) { if(aug==-1||aug>edge[i].cap) aug=edge[i].cap; pre[v]=u; u=v; if(v==end) { maxflow+=aug; for(u=pre[u]; v!=start; v=u,u=pre[u]) { edge[cur[u]].cap-=aug; edge[cur[u]^1].cap+=aug; } aug=-1; } goto loop; } } int mindis=nodenum; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if(edge[i].cap&&mindis>dis[v]) { cur[u]=i; mindis=dis[v]; } } if((--gap[dis[u]])==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return maxflow; } bool vis[maxn]; bool dfs(int u,int pre) { vis[u]=true; int biu=-1; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; if(edge[i].cap>0) { if(vis[v]) return true; if(dfs(v,u)) return true; } if(biu==-1)head[u]=edge[i].next; else edge[biu].next=edge[i].next; biu=i; } vis[u]=false; return false; } bool check(int NodeNum) { memset(vis,false,sizeof(vis)); for(int i=0;i<=NodeNum;i++) { if(dfs(i,-1)) return true; } return false; } int Scan() { int res = 0, ch, flag = 0; if((ch = getchar()) == '-') //判断正负输入外挂。。。 flag = 1; else if(ch >= '0' && ch <= '9') //得到完整的数 res = ch - '0'; while((ch = getchar()) >= '0' && ch <= '9' ) res = res * 10 + ch - '0'; return flag ? -res : res; } int r[MAXN],c[MAXN]; int main() { int t,TOT=0; int rsum,csum,sum ; int n,m; int S,T; ///scanf("%d",&t); t=Scan(); while(t--) { n=Scan(),m=Scan(); //scanf("%d%d",&n,&m); init(); rsum=csum=0; for(int i=1; i<=n; i++) { ///scanf("%d",&sum); sum=Scan(); csum+=sum; c[i]=sum; } for(int i=1; i<=m; i++) { //scanf("%d",&sum); sum=Scan(); rsum+=sum; r[i]=sum; } printf("Case #%d:",++TOT); if(rsum!=csum) { printf(" So naive!\n"); continue; } S=0,T=n+m+1; int NodeNum=T+1; for(int i=1; i<=n; i++) { addedge(S,i,c[i]); } for(int i=1; i<=m; i++) { addedge(i+n,T,r[i]); } for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) addedge(i,j+n,9); } if(sap(S,T,NodeNum)!=rsum) { printf(" So naive!\n"); continue; } if(check(NodeNum)) printf(" So young!\n"); else printf(" So simple!\n"); } return 0; }