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 }

 

posted @ 2014-07-30 20:52  james47  阅读(284)  评论(0编辑  收藏  举报