HDOJ 4975 A simple Gaussian elimination problem【最大流Dinic+判环】
来源:互联网 发布:淘宝进口食品货源 编辑:程序博客网 时间:2024/06/14 03:43
A simple Gaussian elimination problem.
TimeLimit: 2000/1000 MS (Java/Others) Memory Limit:65536/65536 K (Java/Others)
Total Submission(s): 1779 Accepted Submission(s): 546
Problem Description
Dragonis 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 sumof each row and column. Since he thought the map will be useless after he gotthe sums, he destroyed the table after that.
However Dragon's mom came back and found what he had done. She would givedragon a feast if Dragon could reconstruct the table, otherwise keep Dragonhungry. Dragon is so young and so simple so that the original numbers in thetable 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 testcases. Following T blocks, each block describes one test case.
There are three lines for each block. The first line contains two integersN(<=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 theoriginal table, just output: "So naive!", else if we can reconstructthe 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!
题意:给出一个n*m的矩阵,矩阵的每个格点上为0~9的数字,告诉你矩阵每一行每一列的和,问是否可以还原矩阵。若可还原,还原方法是否唯一。
分析:
先进行特判,如果所有行的和不等于所有列的和,显然无法还原。然后利用网络流的最大流模型。
建立源点S,连入各个行点,权值为该行的数字和
建立汇点T,将各个列点连入汇点T,权值为该列的数字和
将各个行点连入汇点T,权值为9,表示每一条边上最大可取9.
跑一遍Dinic求最大流,如果最大流为满流,说明可以还原,否则表示不可以还原。
判断还原方法是否唯一:只要判断残余网络中是否存在有向环即可:
#include <cstdio>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 505;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;struct node{ int u,v,w,next;}e[maxn*maxn*10];int r,c,cnt;int ss,tt;int sum1,sum2;int head[maxn*2];int cur[maxn*2];int dis[maxn*2];int vis[maxn*2];vector<int>vec[maxn*2];void add(int u,int v,int w){ e[cnt].u=u; e[cnt].v=v; e[cnt].w=w; e[cnt].next=head[u]; head[u]=cnt++;}int bfs(){ mst(dis,0); dis[ss]=1; queue<int >q; q.push(ss); while(!q.empty()) { int u=q.front(); //if(u==tt) return 1; //两种写法,效率待考察 q.pop(); for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].v; int w=e[i].w; if(w&&dis[v]==0) { dis[v]=dis[u]+1; q.push(v); } } } if(dis[tt]>0) return 1; return 0;}int dfs(int u,int maxflow){ if(tt==u) return maxflow; int ret=0; for(int &i=cur[u];i!=-1;i=e[i].next) { int v=e[i].v; int w=e[i].w; if(w&&dis[v]==dis[u]+1) { int add=dfs(v,min(maxflow-ret,w)); e[i].w-=add; e[i^1].w+=add; ret+=add; if(ret==maxflow) return ret; } } return ret;}bool DFS_huan(int now,int pre){ vis[now]=1; for(int i=0;i<vec[now].size();i++) { int v=vec[now][i]; if(v==pre) continue; if(vis[v]==1) return 1; if(DFS_huan(v,now)) return 1; } vis[now]=0; //回溯,如果不回溯而是每个点搜的时候都对vis数组清空的话,时间由0ms退化到280ms return 0;}bool judge(){ for(int i=0;i<=tt;i++) { vec[i].clear(); } mst(vis,0); for(int i=0;i<cnt;i++) { if(e[i].w>0) { vec[e[i].u].push_back(e[i].v); } } for(int i=1;i<=r;i++) { if(DFS_huan(i,-1)) return 1; } return 0;}int Dinic(){ int ans=0; while(bfs()) { memcpy(cur,head,sizeof(head)); //用以引用,提高效率,如不加,此题会TLE ans+=dfs(ss,INF); } return ans;}int main(){ int cas=1; rush() { cnt=0; mst(head,-1); scanf("%d%d",&r,&c); ss=r+c+1; tt=ss+1; int x; sum1=sum2=0; for(int i=1;i<=r;i++) { scanf("%d",&x); add(ss,i,x); add(i,ss,0); sum1+=x; } for(int i=1;i<=c;i++) { scanf("%d",&x); add(i+r,tt,x); add(tt,i+r,0); sum2+=x; } for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) { int u=i; int v=j+r; add(u,v,9); add(v,u,0); } printf("Case #%d: ",cas++); if(sum1!=sum2) { //printf("1 "); puts("So naive!"); continue; } int ans=Dinic(); if(ans!=sum1) { //printf("2 "); puts("So naive!"); continue; } if(judge()) { puts("So young!"); } else puts("So simple!"); } return 0;}
- HDOJ 4975 A simple Gaussian elimination problem【最大流Dinic+判环】
- hdu 4975 A simple Gaussian elimination problem【最大流Dinic+思维+判环】好题!
- HDOJ 4975 A simple Gaussian elimination problem.
- HDOJ 4975: A simple Gaussian elimination problem.
- hdoj 4975 A simple Gaussian elimination problem. 【最大流唯一性判断】
- HDU 4975 A simple Gaussian elimination problem.(网络流 + 强联通判环)
- HDU 4975 A simple Gaussian elimination problem.(网络最大流)
- hdu - 4975 - A simple Gaussian elimination problem.(最大流)
- hdu 4975A simple Gaussian elimination problem. 最大流
- HDU-4975-A simple Gaussian elimination problem.
- HDU -- 4975 A simple Gaussian elimination problem.
- HDU 4975 A simple Gaussian elimination problem
- HDU 4975 A simple Gaussian elimination problem 网络流
- HDU 4975 A simple Gaussian elimination problem网络流
- HDOJ 4888 Redraw Beautiful Drawings && HDOJ 4975 A simple Gaussian elimination problem
- HDU 4975 (杭电多校 #10 1005题)A simple Gaussian elimination problem.(网络流之最大流)
- HDU 4975 (杭电多校 #10 1005题)A simple Gaussian elimination problem.(网络流之最大流)
- A simple Gaussian elimination problem.(hdu4975)网络流+最大流
- jzoj4216. 【NOIP2015模拟9.12】平方和(splay+码量)
- 正则表达式
- Peewee中文文档【五】:贡献
- (6)用户、组与权限管理
- java实现url转码、解码
- HDOJ 4975 A simple Gaussian elimination problem【最大流Dinic+判环】
- python学习小记
- Android 全局背景音乐
- UNIX网络编程卷1:套接字联网-第4章:基本TCP套接字编程1
- Eclipse设置
- 关于 opencv 中的直方图
- 如何使用ffmpeg分离视频和音频t
- 动态规划
- 实现 计算两个三维坐标点的 距离