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?
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.
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;
}
相關文章
- 為什麼日本德國沒有一流網際網路企業?
- 判斷網路是否連線
- iOS判斷是否存在網路iOS
- Android 判斷網路是否正常Android
- 唯品會違規理財 網際網路金融邊界何在?
- JS 射線法 判斷點是否在多邊形內部JS斷點
- 判斷點是否在多邊形內的Python實現及小應用(射線法)斷點Python
- 判斷是否能連線網際網路
- 判斷點是否在多邊形內斷點
- 判斷點是否在多邊形內部斷點
- 判斷字串是否為空字串
- 網路遊戲公司如何判斷是否被攻擊?遊戲
- 一句話判斷網路是否聯通
- Android檢測網路狀態,判斷當前網路是否可用Android
- 省級一流課程
- Python中怎麼判斷路徑是否為目錄?Python
- python判斷是否為listPython
- js判斷字串是否為空JS字串
- mysql如何判斷是否為空MySql
- python 判斷是否為中文Python
- JavaScript判斷字串是否為空JavaScript字串
- java判斷字串是否為空Java字串
- js判斷物件是否為空JS物件
- 判斷是否為迴文字元字元
- 判斷物件值是否為空物件
- java判斷物件是否為空Java物件
- hdu4280 網路流+掛(無向圖的網路流注意建邊)
- C++判斷是否為閏年C++
- 如何判斷 JavaScript 物件是否為空?JavaScript物件
- 33判斷字串是否為迴文字串
- python判斷list是否為空Python
- Delphi Variant 判斷是否為空
- 【網路流】網路流基本概念
- Linux shell指令碼判斷伺服器網路是否可以上網Linux指令碼伺服器
- 判斷一個物件是否為空物件,判斷一個物件中是否有空值物件
- C#判斷字串是否為日期格式C#字串
- postgresql判斷是否為數字的方法SQL
- 如何在Java中判斷是否為空Java