【最大流】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 int MAX_E = MAX_N * MAX_N * 5;
 11 const int INF = 0x3f3f3f3f;
 12 
 13 struct Edge {
 14     int v, nxt;
 15     long long cap;
 16     Edge() {
 17 
 18     }
 19     Edge(int _v, int _nxt, long long _cap) {
 20         v = _v, nxt = _nxt, cap = _cap;
 21     }
 22 };
 23 
 24 Edge G[MAX_E];
 25 int edgecnt, head[MAX_N];
 26 int gap[MAX_N], d[MAX_N];
 27 
 28 struct Isap {
 29     int n, s, t;
 30     void init(int n, int s, int t) {
 31         this->n = n, this->s = s, this->t = t;
 32         edgecnt = 0;
 33         memset(head, -1, sizeof head);
 34     }
 35     void addedge(int u, int v, long long cap) {
 36         G[edgecnt] = Edge(v, head[u], cap);
 37         head[u] = edgecnt++;
 38         G[edgecnt] = Edge(u, head[v], 0);
 39         head[v] = edgecnt++;
 40     }
 41     long long dfs(int u, long long tot) {
 42         if (u == t) return tot;
 43         int minh = n - 1;
 44         long long leave = tot;
 45         for (int i = head[u]; ~i && leave; i = G[i].nxt) {
 46             int v = G[i].v;
 47             if (G[i].cap > 0) {
 48                 if (d[v] + 1 == d[u]) {
 49                     long long c = dfs(v, min(leave, G[i].cap));
 50                     G[i].cap -= c;
 51                     G[i ^ 1].cap += c;
 52                     leave -= c;
 53                     if (d[s] >= n) 
 54                         return tot - leave;
 55                 }
 56                 minh = min(minh, d[v]);
 57             }
 58         }
 59         if (leave == tot) {
 60             --gap[d[u]];
 61             if (gap[d[u]] == 0) d[s] = n;
 62             d[u] = minh + 1;
 63             ++gap[d[u]];
 64         }
 65         return tot - leave;
 66     }
 67     long long maxFlow() {
 68         long long ret = 0;
 69         memset(gap, 0, sizeof gap);
 70         memset(d, 0, sizeof d);
 71         gap[0] = n;
 72         while (d[s] < n) {
 73             ret += dfs(s, INF);
 74         }
 75         return ret;
 76     }
 77 };
 78  
 79 int n, m, k;
 80 int mat[MAX_N][MAX_N];
 81 int c[MAX_N][MAX_N];
 82 
 83 inline bool rd(int &n){    
 84     int x = 0, tmp = 1;    
 85     char c = getchar();    
 86     while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    
 87     if(c == EOF) return false;    
 88     if(c == '-') c = getchar(), tmp = -1;    
 89     while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    
 90     n = x*tmp;    
 91     return true;  
 92 }    
 93 
 94 int main() {
 95     int T;
 96     scanf("%d", &T);
 97     int cas = 0;
 98     while (T-- > 0) {
 99         Isap ans;
100         scanf("%d%d", &n, &m);
101         k = 9;
102         ans.init(n + m + 2, 0, n + m + 1);
103         int s = 0, t = n + m + 1;
104         long long sum1 = 0, sum2 = 0;
105         for (int i = 1; i <= n; ++i) {
106             for (int j = 1; j <= m; ++j) {
107                 ans.addedge(i, n + j, k);
108             }
109         }
110         for (int i = 1; i <= n; ++i) {
111             int rowSum = 0;
112             rd(rowSum);
113             sum1 += rowSum;
114             ans.addedge(0, i, rowSum);    
115         }
116         for (int i = 1; i <= m; ++i) {
117             int colSum = 0;
118             rd(colSum);
119             sum2 += colSum;
120             ans.addedge(n + i, t, colSum);
121         }       
122         int q = ans.maxFlow();
123         printf("Case #%d: ", ++cas);
124         if (sum1 != sum2 || q != sum1) puts("So naive!");
125         else {
126             int edge = 0;
127             n = min(n, 200);
128             m = min(m, 200);
129             for (int i = 1; i <= n; ++i) {
130                 for (int j = 1; j <= m; ++j, edge += 2) {
131                     mat[i][j] = G[edge ^ 1].cap;
132                 }
133             }
134             memset(c, false, sizeof c);
135             bool f = false;
136             for (int i = 1; i <= n; ++i) {
137                 for (int j = 1; j <= m; ++j) {
138                     for (int l = j + 1; l <= m; ++l) {
139                         bool f1 = false, f2 = false;
140                         if (mat[i][j] != k && mat[i][l] != 0) {// column j could add, column l could dec 
141                             if (c[l][j]) {
142                                 l = m + 1, j = m + 1, i = n + 1;
143                                 f = true;
144                             }
145                             f1 = true;
146                         }
147                         if (mat[i][j] != 0 && mat[i][l] != k) {// column l could add, column j could dec
148                             if (c[j][l]) {
149                                 l = m + 1, j = m + 1, i = n + 1;
150                                 f = true;
151                             }
152                             f2 = true;
153                         }
154                         if (f1) c[j][l] = true;
155                         if (f2) c[l][j] = true;
156                     }
157                 }
158             }
159             if (f) puts("So young!");
160             else {
161                 puts("So simple!");
162             } 
163         }
164     } 
165     return 0;
166 }
View Code

 

转载于:https://www.cnblogs.com/Rojo/p/4684466.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值