hdu4975 网络流及‘删边法’判是否为唯一流

来源:互联网 发布:凯撒博尔吉亚 知乎 编辑:程序博客网 时间:2024/05/23 18:36

http://acm.hdu.edu.cn/showproblem.php?pid=4975



Problem Description
Dragon is studying math. One day, he drew a table with several rows and columns, randomly wrote numbers on each elements of the table. Then he counted the sum of each row and column. Since he thought the map will be useless after he got the sums, he destroyed the table after that.

However Dragon's mom came back and found what he had done. She would give dragon a feast if Dragon could reconstruct the table, otherwise keep Dragon hungry. Dragon is so young and so simple so that the original numbers in the table are one-digit number (e.g. 0-9).

Could you help Dragon to do that?
 

Input
The first line of input contains only one integer, T(<=30), the number of test cases. Following T blocks, each block describes one test case.

There are three lines for each block. The first line contains two integers N(<=500) and M(<=500), showing the number of rows and columns.

The second line contains N integer show the sum of each row.

The third line contains M integer show the sum of each column.
 

Output
Each output should occupy one line. Each line should start with "Case #i: ", with i implying the case number. For each case, if we cannot get the original table, just output: "So naive!", else if we can reconstruct the table by more than one ways, you should output one line contains only: "So young!", otherwise (only one way to reconstruct the table) you should output: "So simple!".
 

Sample Input
31 1552 20 100 102 22 22 2
 

Sample Output
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;}
1 0