题目链接: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!
 
Source

题意:

给出每行每列的和,问是否存在这种表格;每一个小格放的数字仅仅能是0--9。

官方题解:http://blog.sina.com.cn/s/blog_6bddecdc0102v01l.html

代码例如以下:(套用别人HDU4888的模板)

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
#define ll __int64
#define eps 1e-8
const ll Mod=(1e9+7);
const int maxn = 510;
const int maxm = 50100; int n,m,k;
int r[maxn],c[maxn];
int ma[maxn][maxn]; const int maxnode = 10000 + 5;
const int maxedge = 2*1000000 + 5;
const int oo = 1000000000;
int node, src, dest, nedge;
int head[maxnode], point[maxedge], next1[maxedge], flow[maxedge], capa[maxedge];//point[x]==y表示第x条边连接y,head,next为邻接表,flow[x]表示x边的动态值,capa[x]表示x边的初始值
int dist[maxnode], Q[maxnode], work[maxnode];//dist[i]表示i点的等级
void init(int _node, int _src, int _dest) //初始化,node表示点的个数,src表示起点,dest表示终点
{
node = _node;
src = _src;
dest = _dest;
for (int i = 0; i < node; i++) head[i] = -1;
nedge = 0;
}
void addedge(int u, int v, int c1, int c2) //添加一条u到v流量为c1,v到u流量为c2的两条边
{
point[nedge] = v, capa[nedge] = c1, flow[nedge] = 0, next1[nedge] = head[u], head[u] = (nedge++);
point[nedge] = u, capa[nedge] = c2, flow[nedge] = 0, next1[nedge] = head[v], head[v] = (nedge++);
}
bool dinic_bfs()
{
memset(dist, 255, sizeof (dist));
dist[src] = 0;
int sizeQ = 0;
Q[sizeQ++] = src;
for (int cl = 0; cl < sizeQ; cl++)
for (int k = Q[cl], i = head[k]; i >= 0; i = next1[i])
if (flow[i] < capa[i] && dist[point[i]] < 0)
{
dist[point[i]] = dist[k] + 1;
Q[sizeQ++] = point[i];
}
return dist[dest] >= 0;
}
int dinic_dfs(int x, int exp)
{
if (x == dest) return exp;
for (int &i = work[x]; i >= 0; i = next1[i])
{
int v = point[i], tmp;
if (flow[i] < capa[i] && dist[v] == dist[x] + 1 && (tmp = dinic_dfs(v, min(exp, capa[i] - flow[i]))) > 0)
{
flow[i] += tmp;
flow[i^1] -= tmp;
return tmp;
}
}
return 0;
}
int dinic_flow()
{
int result = 0;
while (dinic_bfs())
{
for (int i = 0; i < node; i++) work[i] = head[i];
while (1)
{
int delta = dinic_dfs(src, oo);
if (delta == 0) break;
result += delta;
}
}
return result;
}
//建图前,执行一遍init();
//加边时,执行addedge(a,b,c,0),表示点a到b流量为c的边建成(注意点序号要从0開始)
//求解最大流执行dinic_flow(),返回值即为答案 bool judge(int sumrow)
{
int flow = 1,cost = 0;
for(int i = 1; i <= n; i++)
for(int j = n+1; j <= n+m; j ++)
addedge(i,j,k,0);
flow=dinic_flow();
if(flow != sumrow)
return false;
return true;
}
int main()
{
//k为能填原图能填的数字的最大值
int t;
int cas = 0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
k = 9;//最多能填9
init(n+m+2,0,n+m+1);
int flag = 0;
int sumrow = 0,colrow = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d",&r[i]);
addedge(0,i,r[i],0);
sumrow += r[i];
if(r[i]<0 || r[i]>m*k)
flag = 1;
}
for(int j = 1; j <= m; j ++)
{
scanf("%d",&c[j]);
addedge(j+n,n+m+1,c[j],0);
colrow += c[j];
if(c[j]<0 || c[j]>n*k)
flag = 1;
}
if(sumrow != colrow)
{
printf("Case #%d: So naive!\n",++cas);
continue;
}
if(!judge(sumrow))
flag = 1;
if(flag == 1)
{
printf("Case #%d: So naive!\n",++cas);
continue;
}
memset(ma,-1,sizeof(ma));
int i,j;
for(i=1; i<=n; i++)
if(r[i]==0)
for(j=1; j<=m; j++)
ma[i][j]=0;
for(j=1; j<=m; j++)
if(c[j]==0)
for(i=1; i<=n; i++)
ma[i][j]=0;
int tt=2;
int sum,num,temp;
while(tt--)
{
for(i=1; i<=n; i++)
{
if(r[i]==0)
{
for(j=1; j<=m; j++)
if(ma[i][j]==-1)
ma[i][j]=0;
continue;
}
sum=0;
num=0;
for(j=1; j<=m; j++)
{
if(ma[i][j]==-1)
{
num++;
temp=j;
sum+=min(k,c[j]);
}
}
if(num==1)
{
ma[i][temp]=r[i];
r[i]-=ma[i][temp];
c[temp]-=ma[i][temp];
continue;
}
else if(sum==r[i])
{
for(j=1; j<=m; j++)
{
if(ma[i][j]==-1)
{
ma[i][j]=min(k,c[j]);
r[i]-=ma[i][j];
c[j]-=ma[i][j];
}
}
}
}
for(j=1; j<=m; j++)
{
if(c[j]==0)
{
for(i=1; i<=n; i++)
if(ma[i][j]==-1)
ma[i][j]=0;
continue;
}
sum=0;
num=0;
for(i=1; i<=n; i++)
{
if(ma[i][j]==-1)
{
num++;
temp=i;
sum+=min(k,r[i]);
}
}
if(num==1)
{
ma[temp][j]=c[j];
r[temp]-=ma[temp][j];
c[j]-=ma[temp][j];
continue;
}
else if(sum==c[j])
{
for(i=1; i<=n; i++)
{
if(ma[i][j]==-1)
{
ma[i][j]=min(k,r[i]);
r[i]-=ma[i][j];
c[j]-=ma[i][j];
}
}
}
}
}
flag=0;
for(i=1; i<=n; i++)
if(r[i]!=0)
{
flag=1;
break;
}
for(j=1; j<=m; j++)
if(c[j]!=0)
{
flag=1;
break;
}
if(flag==1)
printf("Case #%d: So young!\n",++cas);
else
{
printf("Case #%d: So simple!\n",++cas);
/* for(i=1; i<=n; i++)
{
for(j=1; j<m; j++)
printf("%d ",ma[i][j]);
printf("%d\n",ma[i][m]);
}*/
}
}
return 0;
}

hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)的更多相关文章

  1. HDU 4975 A simple Gaussian elimination problem.

    A simple Gaussian elimination problem. Time Limit: 1000ms Memory Limit: 65536KB This problem will be ...

  2. hdu - 4975 - A simple Gaussian elimination problem.(最大流量)

    意甲冠军:要在N好M行和列以及列的数字矩阵和,每个元件的尺寸不超过9,询问是否有这样的矩阵,是独一无二的N(1 ≤ N ≤ 500) , M(1 ≤ M ≤ 500). 主题链接:http://acm ...

  3. hdu 4975 A simple Gaussian elimination problem 最大流+找环

    原题链接 http://acm.hdu.edu.cn/showproblem.php?pid=4975 这是一道很裸的最大流,将每个点(i,j)看作是从Ri向Cj的一条容量为9的边,从源点除法连接每个 ...

  4. HDOJ 4975 A simple Gaussian elimination problem.

    和HDOJ4888是一样的问题,最大流推断多解 1.把ISAP卡的根本出不来结果,仅仅能把全为0或者全为满流的给特判掉...... 2.在残量网络中找大于2的圈要用一种类似tarjian的方法从汇点開 ...

  5. A simple Gaussian elimination problem.(hdu4975)网络流+最大流

    A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65 ...

  6. hdu4975 A simple Gaussian elimination problem.(正确解法 最大流+删边判环)(Updated 2014-10-16)

    这题标程是错的,网上很多题解也是错的. http://acm.hdu.edu.cn/showproblem.php?pid=4975 2014 Multi-University Training Co ...

  7. A simple Gaussian elimination problem.

    hdu4975:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:给你一个n*m的矩阵,矩阵中的元素都是0--9,现在给你这个矩阵的每一行和每一列的和 ...

  8. hdu4975 A simple Gaussian elimination problem.(最大流+判环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:和hdu4888基本一样( http://www.cnblogs.com/a-clown/ ...

  9. hdu 4972 A simple dynamic programming problem(高效)

    pid=4972" target="_blank" style="">题目链接:hdu 4972 A simple dynamic progra ...

随机推荐

  1. 把一个数组向右循环移动k位要求时间复杂度为O(n)

    今晚做了下某公司的网络笔试题,好久没刷题了,现在渣得要死,里面有道程序设计题是 把一个数组向右循环移动k位要求时间复杂度为O(n) 给的方法定义为 public void solution(int a ...

  2. HDU 3746 Cyclic Nacklace KMP

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3746 KMP算法—— AC代码: #include <iostream> #include ...

  3. leetCode 24. Swap Nodes in Pairs (双数交换节点) 解题思路和方法

    Swap Nodes in Pairs  Given a linked list, swap every two adjacent nodes and return its head. For exa ...

  4. Java对象序列化与反序列化一 JSON

    Java对象序列化与反序列化一 JSON 1. 依赖库 jackson-all-1.6.1.jar 2. 代码 public class Student {    private String nam ...

  5. <input type="text">文本输人框

    type类型: text  文本框 password  口令密码输人框 reset  重置或清除 buttou  命令按钮 checkbox  复选框 radio  单选框 submit  提交 fi ...

  6. EF使用时异常:对一个或多个实体的验证失败。有关详细信息

    //最顶级异常中是不提示具体哪个字段验证失败,必须到详细异常类型中查看 try { //EF操作 } catch (System.Data.Entity.Validation.DbEntityVali ...

  7. Codeforces 18C C. Stripe

    Codeforces 18C  C. Stripe 链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=86640#problem/E 题 ...

  8. strcpy_s

    char src[5]="abcd"; char *des=new char[str.length(src)+1];   // length()不计\0 strcpy_s(des, ...

  9. 「C」 数组、字符串、指针

    一.数组 (一)数组 概念:用来存储一组数据的构造数据类型 特点:只能存放一种类型的数据,如全部是int型或者全部是char型,数组里的数据成为元素. (二)数组的定义 格式: 类型 数组名[元素个数 ...

  10. BZOJ 1660: [Usaco2006 Nov]Bad Hair Day 乱发节( 单调栈 )

    维护一个h严格递减的栈 , 出栈时计算一下就好了.. ------------------------------------------------------------------------- ...