【最大流】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 }