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

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

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!
/**
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;
}

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

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!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-28 05:57:20

hdu4975 网络流及‘删边法’判是否为唯一流的相关文章

hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)

http://acm.hdu.edu.cn/showproblem.php?pid=4975 A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 579    Accepted Submission(s): 194 Problem Description Drag

HDU 4344 随机法判素数(费马小定理

#include <cstdio> #include <ctime> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; const int N = 108; const int S = 10; ll mult_mod(ll a, ll b, ll c) { a %= c; b %= c; ll ret = 0; while(b) { if(b&am

HDOJ 题目2444 The Accomodation of Students(染色法判二分图,最大匹配)

The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2943    Accepted Submission(s): 1376 Problem Description There are a group of students. Some of them may know each o

poj2942圆桌骑士(点双连通分量+二分图染色法判奇圈)

之前一直不明白点双连通分量能用来干嘛,比如边双连通分量可以问加几条边能变成边双连通,这个题目是这样的,每个圆桌会议至少三个骑士参加,因为需要表决意见,所以骑士数目必须是奇数个,直到那些骑士互相憎恨,也就是不能坐在一起的,把能坐在一起的建边,求无法参加任何会议的骑士的个数,重点是任何会议,这点非常关键,这道题之前一直卡在这里,还有就是有的人属于好几种双连通分量,所以全部标记之后再减掉比较好,至于奇数个怎么处理呢,今天才知道原来二分图的判断可以解决奇圈的问题,因为如果是二分图的话,我们染色,相邻的涂

【转】三种常用的字符串判空串方法

1. 三种常用的字符串判空串方法:Length法:bool isEmpty = (str.Length == 0);Empty法:bool isEmpty = (str == String.Empty);General法:bool isEmpty = (str == ""); 2. 深入内部机制:要探讨这三种方法的内部机制,我们得首先看看.NET是怎样实现的,也就是要看看.NET的源代码!然而,我们哪里找这些源代码呢?我们同样有三种方法:Rotor法:一个不错的选择就是微软的Rotor

【WIN10】判斷程序運行在哪個平台

其實....... 微軟貌似並沒有提供這樣的接口,無法判斷是運行在PC,還是運行在Mobile,抑或是Xbox,或是其它. 微軟只提供了用戶交互模式的獲取:鼠標.觸摸. 或許微軟認為,WIN10不論運行在什麼平台,它都是WIN10,不是WIN10 ON PC,或是WIN10 ON MOBILE等東東.他們只有用戶操作的方式不同,而不存在說有兩個系統,他們均是WIN10. 我寫了一個判斷是否運行在移動端的函數: public static bool IsRunningOnMobile() { re

UVA 1364 - Knights of the Round Table (找双连通分量 + 二分图染色法判断)

都特么别说话,我先A了这道题! 卧槽啊.....! 题意来自 kuangbin: 亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突, 并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1.  相互憎恨的两个骑士不能坐在直接相邻的2个位置: 2.  出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果. 注意:1.所给出的憎恨关系一定是双向的,不存在单向憎恨关系. 2.由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士. 即每个骑士的座位两边都

数据库问题5-SYS.SYSPROCESSES使用和查找死锁

http://blog.sina.com.cn/s/blog_62c4727d0100jc5z.html (一)理論部份 sys.sysprocesses (Transact-SQL) http://technet.microsoft.com/zh-tw/library/ms179881.aspx 包含在 SQL Server 執行個體上執行之處理序的相關資訊.這些處理序可以是用戶端處理序或系統處理序.若要存取 sysprocesses,您必須在 master 資料庫內容中,或者,您必須使用 m

usaco-4.1-stall4-passed

这个题是最有意思的了,一次性通过,网络流,最大流法,匈牙利法,网上有一篇趣写算法系列--趣写算法系列之--匈牙利算法 这是我见过很有趣的东东了,推荐给大家, /* ID: qq104801 LANG: C++ TASK: stall4 */ #include <iostream> #include <fstream> #include <cstring> #include <vector> #include <queue> #include &l