HDOJ 4888 Redraw Beautiful Drawings 最大流 dinic+当前弧优化
http://acm.hdu.edu.cn/showproblem.php?pid=4888
今天人品太差,这题死磕了一整天。。开始的死循环,WA。。再到2min。。改得和别人AC的代码几乎一样了,在本地,别人跑2s,我跑10s。。最后加了个当前弧优化,怒跑265ms。。暂时进入前10。。中间很多问题也不明不白的。。
这题,求是否有可行解其实是一道成题了,然后它增加了一个判断多解的要求。建图是代表行的n个点和源点相连,容量为该行的和,代表列的m个点和汇点相连,容量为该列的和,每个行和每个列相连,容量为K,跑一遍最大流,看是否满流(sumr == sumc == maxflow)。多解是看残余网络上是否有长度大于2的环,可以dfs找到。也有用o(n^3)暴力判多解的,具体百度。。唯一解的话,K减去i行到j列的边的剩余容量即是该点所填的数。
1 #include<stdio.h> 2 #include<string.h> 3 4 int n, m, k, st, ed, esize, w, maxflow, cas; 5 int matrix[500][500]; 6 int lv[1000], en[1000], q[1000], cur[1000]; 7 int vis[600000]; 8 bool vv[1000]; 9 struct Edge{ 10 int v, w, n; 11 } e[600000]; 12 void addedge(int u, int v, int w) 13 { 14 e[esize].v = v; e[esize].w = w; e[esize].n = en[u]; 15 en[u] = esize ++; 16 e[esize].v = u; e[esize].w = 0; e[esize].n = en[v]; 17 en[v] = esize ++; 18 } 19 bool bfs() 20 { 21 memset(lv, -1, sizeof(lv)); 22 int head, tail; 23 lv[st] = head = tail = 0; 24 q[tail++] = st; 25 while(head < tail) 26 { 27 int u = q[head++]; 28 for (int t = en[u]; t != -1; t = e[t].n){ 29 int v = e[t].v; 30 if (lv[v] == -1 && e[t].w > 0){ 31 lv[v] = lv[u] + 1; 32 q[tail++] = v; 33 if (v == ed) return 1; 34 } 35 } 36 } 37 return 0; 38 } 39 int dfs(int u, int maxf) 40 { 41 if (maxf == 0) return 0; 42 if (u == ed) return maxf; 43 int ans = 0, flow, tmp; 44 for (int &t = cur[u]; t != -1; t = e[t].n){ 45 int v = e[t].v; 46 if (e[t].w > 0 && lv[v] == lv[u] + 1){ 47 tmp = maxf - ans; 48 if (e[t].w < tmp) tmp = e[t].w; 49 flow = dfs(v, tmp); 50 if (flow > 0){ 51 e[t].w -= flow; 52 ans += flow; 53 e[t^1].w += flow; 54 if (maxf == ans) return ans; 55 } 56 else lv[v] = -10;//这个没有必要了 57 } 58 } 59 lv[u] = -10;//没有必要 60 return ans; 61 } 62 bool findloop(int u, int fa) 63 { 64 for (int t = en[u]; t != -1; t = e[t].n){ 65 int v = e[t].v; 66 if (e[t].w <= 0 || v == fa || v == st || v == ed) continue; 67 if (vv[v]) return true; 68 if (vis[t] == cas) continue; 69 vis[t] = cas; 70 vv[v] = true; 71 if (findloop(v, u)) return true; 72 vv[v] = false; 73 } 74 return false; 75 } 76 bool find() 77 { 78 memset(vv, false, sizeof(vv)); 79 for (int i = 1; i <= n; i++){ 80 vv[i] = true; 81 if (findloop(i, st)) return true; 82 vv[i] = false; 83 } 84 return false; 85 } 86 int main() 87 { 88 memset(vis, 0, sizeof(vis)); 89 cas = 0; 90 while(scanf("%d%d%d", &n, &m, &k) != EOF) 91 { 92 cas ++; 93 memset(en, -1, sizeof(en)); 94 esize = 0; 95 st = n+m+1, ed = n+m+2; 96 int sumr = 0, sumc = 0; 97 for (int i = 1; i <= n; i++){ 98 scanf("%d", &w); 99 addedge(st, i, w); 100 sumr += w; 101 } 102 for (int j = n+1; j <= n+m; j++){ 103 scanf("%d", &w); 104 addedge(j, ed, w); 105 sumc += w; 106 } 107 if (sumr != sumc){ 108 printf("Impossible\n"); 109 continue; 110 } 111 for (int i = 1; i <= n; i++) 112 for (int j = n+1; j <= n+m; j++) 113 addedge(i, j, k); 114 maxflow = 0; 115 while(bfs()){ 116 for (int i = 1; i <= n+m+2; i++) cur[i] = en[i]; 117 maxflow += dfs(st, 7000000); 118 } 119 if (maxflow == sumr){ 120 if (find()) 121 printf("Not Unique\n"); 122 else{ 123 printf("Unique\n"); 124 for (int u = 1; u <= n; u++){ 125 for (int t = en[u]; t != -1; t = e[t].n){ 126 int v = e[t].v; 127 if (v > n) 128 matrix[u][v-n] = k-e[t].w; 129 } 130 } 131 for (int i = 1; i <= n; i++){ 132 for (int j = 1; j < m; j++) 133 printf("%d ", matrix[i][j]); 134 printf("%d\n", matrix[i][m]); 135 } 136 } 137 } 138 else{ 139 printf("Impossible\n"); 140 continue; 141 } 142 } 143 return 0; 144 }