HDU 4975 A simple Gaussian elimination problem.

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

题意:同HDU 4888。给N行M列,每行之和,每列之和,判断矩阵是不是唯一。

题解:网络流。源点和每行之和建边,容量为和;汇点和没列之和建边,容量为和;行之和和列之和建边,容量为9(每位只能是0~9)。

    判断可行性:行之和的和是否等于列之和的和;是否满流。

    判断唯一解:残留网络里是否有长度大于等于2的环

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <cstdlib>
  5 #include <string>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <map>
  9 #include <set>
 10 #include <queue>
 11 #include <stack>
 12 #include <cmath>
 13 #include <ctime>
 14 #include <functional>
 15 #include <cctype>
 16
 17 using namespace std;
 18
 19 typedef __int64 ll;
 20
 21 const int INF=0xfffffff;
 22
 23 const int maxm=500*500*10+10;
 24 const int maxn=510+510;
 25
 26 struct edge{
 27     int to,cap,next;
 28     edge(int to=0,int cap=0,int next=0):to(to),cap(cap),next(next){}
 29 }G[maxm];
 30 int head[maxn],level[maxn];
 31 bool used[maxn];
 32 int g[maxn][maxn];
 33 int sumr,sumc;
 34 int N,M;
 35 int flag;
 36 int idx;
 37 int s,t;
 38
 39 void add_edge(int from,int to,int cap)
 40 {
 41     G[++idx]=edge(to,cap,head[from]);
 42     head[from]=idx;
 43     G[++idx]=edge(from,0,head[to]);
 44     head[to]=idx;
 45 }
 46
 47 bool bfs(int S,int T)
 48 {
 49     memset(level,0xff,sizeof(level));
 50     level[S]=0;
 51     queue<int> q;
 52     q.push(S);
 53     while(!q.empty())
 54     {
 55         int v=q.front();
 56         q.pop();
 57         for(int k=head[v];k!=-1;k=G[k].next)
 58         {
 59             edge &e=G[k];
 60             if(level[e.to]==-1&&e.cap){
 61                 level[e.to]=level[v]+1;
 62                 q.push(e.to);
 63             }
 64         }
 65     }
 66     return level[T]!=-1;
 67 }
 68
 69 int dfs(int v,int f,int T)
 70 {
 71     if(v==T||f==0) return f;
 72     int flow=0;
 73     for(int k=head[v];k!=-1;k=G[k].next)
 74     {
 75         edge &e=G[k];
 76         if(level[e.to]==level[v]+1){
 77             int d;
 78             if((d=dfs(e.to,min(f,e.cap),T))>0){
 79                 G[k].cap-=d;
 80                 G[k^1].cap+=d;
 81                 flow+=d;
 82                 f-=d;
 83                 if(f==0) return flow;
 84             }
 85         }
 86     }
 87     level[v]=-1;
 88     return flow;
 89 }
 90
 91 int max_flow(int s,int t)
 92 {
 93     int flow=0;
 94     int f;
 95     while(bfs(s,t)==1)
 96     {
 97         while((f=dfs(s,INF,t))>0)
 98         {
 99             flow+=f;
100         }
101     }
102     return flow;
103 }
104
105 int dfs_loop(int u,int rev)
106 {
107     for(int &k=head[u];k!=-1;k=G[k].next)
108     {
109         if(k==(rev^1)) continue;
110         if(G[k].cap){
111             if(used[G[k].to]) return 1;
112             used[G[k].to]=true;
113             if(dfs_loop(G[k].to,k)==1) return 1;
114             used[G[k].to]=false;
115         }
116     }
117     return 0;
118 }
119
120 int judge()
121 {
122     for(int i=1;i<=N;i++)
123     {
124         if(dfs_loop(i,-1)) return 0;
125     }
126     return 1;
127 }
128
129 void init()
130 {
131     idx=-1;
132     memset(head,0xff,sizeof(head));
133     memset(used,0,sizeof(used));
134     sumr=0;
135     sumc=0;
136     flag=0;
137 }
138
139 int main() {
140     int T;
141     scanf("%d",&T);
142     for(int ca=1;ca<=T;ca++)
143     {
144         init();
145         printf("Case #%d: ",ca);
146         scanf("%d%d",&N,&M);
147         s=0;
148         t=N+M+1;
149         int cr;
150         for(int i=1;i<=N;i++)
151         {
152             scanf("%d",&cr);
153             sumr+=cr;
154             add_edge(s,i,cr);
155             for(int j=1;j<=M;j++)
156             {
157                 add_edge(i,N+j,9);
158             }
159         }
160         int cc;
161         for(int i=1;i<=M;i++)
162         {
163             scanf("%d",&cc);
164             sumc+=cc;
165             add_edge(N+i,t,cc);
166         }
167         int maxflow=max_flow(s,t);
168         if(sumr!=sumc) puts("So naive!");
169         else if(sumr!=maxflow) puts("So naive!");
170         else if(!judge()) puts("So young!");
171         else puts("So simple!");
172     }
173     return 0;
174 }
时间: 2024-07-30 23:33:20

HDU 4975 A simple Gaussian elimination problem.的相关文章

hdu 4975 A simple Gaussian elimination problem.(网络流,判断矩阵是否存在)

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

HDU 4975 A simple Gaussian elimination problem. 网络流+矩阵上的dp

随机输出保平安啊 和hdu4888一个意思,先跑个网络流然后dp判可行. ==n^3的dp过不了,所以把n改成200. ==因为出题人没有把多解的情况放在200*200以外的矩阵. #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; const int MAX_N = 12

HDU 4975 A simple Gaussian elimination problem.(网络最大流)

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): 669    Accepted Submission(s): 222 Problem Description Drag

hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)

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

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

原题链接 http://acm.hdu.edu.cn/showproblem.php?pid=4975 这是一道很裸的最大流,将每个点(i,j)看作是从Ri向Cj的一条容量为9的边,从源点除法连接每个Ri,再从每个Ci连接至汇点.如若最大流不是滿流,则问题无解.这道题的关键就是在于如何判断是否有多解.考虑这样一个事实,若残余网络上有多个点构成一个环,那么流量可在这个环上调整,某条边上多余的流量可以被环上的其他的边弥补回来.所以如果残余网络上存在一个边数大于2的环,那么问题则是多解.我判断是否有环

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

题意:给一个N行M列的数字矩阵的行和以及列和,每个元素的大小不超过9,问这样的矩阵是否存在,是否唯一N(1 ≤ N ≤ 500) , M(1 ≤ M ≤ 500). 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 -->>方法如:http://blog.csdn.net/scnu_jiechao/article/details/40658221 先做hdu - 4888,再来做此题的时候,感觉这题好 SB 呀,将代码提交后自己就 SB 了

【最大流】HDU 4975 A simple Gaussian elimination problem

通道 题意:n*m的矩阵,每个格子可以是0~9,给出各行的和和各列的和,求格子数字唯一方案,或判断无解或不唯一 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <queue> 5 #include <algorithm> 6 7 using namespace std; 8 9 const int MAX_N = 1207; 10 const

hdoj 4975 A simple Gaussian elimination problem. 【最大流唯一性判断】

题目:hdoj 4975 A simple Gaussian elimination problem. 这个题目跟hdoj 4888 一样,只是数据加强了一点,这个题目确实出的不好,尤其数据,争议比较大,但是同时也说明优化有时候还是很有用的. 不懂的可以看这个讲解:点击 这个题目只是加了一点优化,就是判断的时候加入是行和为0,或者满的话,就跳出不用判断,然后就300ms过了.真心牛 AC代码: #include <cstdio> #include <cstring> #includ

HDOJ 4975 A simple Gaussian elimination problem.

和HDOJ4888是一样的问题,最大流推断多解 1.把ISAP卡的根本出不来结果,仅仅能把全为0或者全为满流的给特判掉...... 2.在残量网络中找大于2的圈要用一种类似tarjian的方法从汇点開始找,推断哪些点没有到汇点 A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submiss