HDU 4888 Redraw Beautiful Drawings

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

题意:给行数N和列数M,颜色数K,以及每一行的和,每一列的和。问有没有唯一排列方法。

题解:网络流,建模一直是个大问题……根本建不出……看完题解后恍然大悟……

   建图:源点到每一行建边,容量为此行之和;每一行和每一列建边,容量为K;每一列和汇点建边,容量为此列之和。

   判断是否有解:源点出发的边和到达汇点的  边是否满流。

   判断唯一解:残余网络是否有长度大于二的环。(有多条路可选,不影响总流量)(DFS)

         唯一解的结果:G[i][j]的流量。

第一次存边表……当做模板好了……实在是太弱了……

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <string>
  7 #include <vector>
  8 #include <list>
  9 #include <map>
 10 #include <queue>
 11 #include <stack>
 12 #include <bitset>
 13 #include <algorithm>
 14 #include <numeric>
 15 #include <functional>
 16 #include <set>
 17 #include <fstream>
 18 
 19 using namespace std;
 20 
 21 const int INF=0xfffffff;
 22 const int maxe=410*410*10;
 23 const int maxn=410+410;
 24 
 25 struct edge{
 26     int to,cap,next;
 27     edge(int to=0,int cap=0,int next=0):to(to),cap(cap),next(next){}
 28 }G[maxe];
 29 int head[maxn],level[maxn],nedge;
 30 bool used[maxn];
 31 int g[maxn][maxn];
 32 int sumr,sumc;
 33 int N,M,K;
 34 int flag;
 35 
 36 void add_edge(int from,int to,int cap)
 37 {
 38     G[++nedge]=edge(to,cap,head[from]);
 39     head[from]=nedge;
 40     G[++nedge]=edge(from,0,head[to]);
 41     head[to]=nedge;
 42 }
 43 
 44 bool bfs(int S,int T)
 45 {
 46     memset(level,0xff,sizeof(level));
 47     level[S]=0;
 48     queue<int>q;
 49     q.push(S);
 50     while(!q.empty())
 51     {
 52         int v=q.front();q.pop();
 53         for(int k=head[v];k!=-1;k=G[k].next)
 54         {
 55             edge e=G[k];
 56             if(level[e.to]==-1&&e.cap)
 57             {
 58                 level[e.to]=level[v]+1;
 59                 q.push(e.to);
 60             }
 61         }
 62     }
 63     return level[T]!=-1;
 64 }
 65 
 66 int dfs(int v,int f,int T)
 67 {
 68     if(v==T||f==0) return f;
 69     int flow=0;
 70     for(int k=head[v];k!=-1;k=G[k].next)
 71     {
 72         edge & e=G[k];
 73         if(level[e.to]==level[v]+1)
 74         {
 75             int d;
 76             if((d=dfs(e.to,min(f,e.cap),T))>0)
 77             {
 78                 G[k].cap-=d;
 79                 G[k^1].cap+=d;
 80                 flow+=d;
 81                 f-=d;
 82                 if(f==0) return flow;
 83             }
 84         }
 85     }
 86     level[v]=-1;
 87     return flow;
 88 }
 89 
 90 int max_flow(int s,int t)
 91 {
 92     int flow=0;
 93     int f;
 94     while (bfs(s,t)==1)
 95     {
 96         while((f=dfs(s,INF,t))>0)
 97         {
 98             flow+=f;
 99             //printf("%d
",flow);
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         {
112             if(used[G[k].to]) return 1;
113             used[G[k].to]=true;
114             if(dfs_loop(G[k].to,k)==1) return 1;
115             used[G[k].to]=false;
116         }
117     }
118     return 0;
119 }
120 
121 int judge_loop()
122 {
123     for(int i=1;i<=N;i++)
124     {
125         if(dfs_loop(i,-1))
126         {
127             return 0;
128         }
129     }
130     return 1;
131 }
132 
133 void put()
134 {
135     for(int u=1;u<=N;u++)
136     {
137         for(int k=head[u];k!=-1;k=G[k].next)
138         {
139             int v=G[k].to;
140             if(v>N&&v<=N+M) g[u][v-N]=K-G[k].cap;
141         }
142     }
143     for(int i=1;i<=N;i++)
144     {
145         for(int j=1;j<=M;j++)
146         {
147             if(j>1) printf(" ");
148             printf("%d",g[i][j]);
149         }
150         puts("");
151     }
152 }
153 
154 void init()
155 {
156     memset(head,0xff,sizeof(head));
157     memset(g,0,sizeof(g));
158     memset(used,0,sizeof(used));
159     nedge=-1;
160     sumr=0;
161     sumc=0;
162     flag=0;
163 }
164 
165 int main()
166 {
167    // freopen("/Users/apple/Desktop/暑假/contest 3 B/contest 3 B/in","r",stdin);
168     while(scanf("%d%d%d",&N,&M,&K)!=EOF)
169     {
170         init();
171         int s=0;
172         int t=N+M+1;
173         int cap;
174         for(int i=1;i<=N;i++)
175         {
176             scanf("%d",&cap);
177             sumr+=cap;
178             add_edge(s, i, cap);//s到行之和 s-(1~N)
179             for(int j=1;j<=M;j++)
180             {
181                 add_edge(i,N+j,K);//(1~N)-(N+1~N+M)
182             }
183         }
184         for(int i=1;i<=M;i++)
185         {
186             scanf("%d",&cap);
187             sumc+=cap;
188             add_edge(N+i,t,cap);//(N+1~N+M)-t
189         }
190         int flow1=max_flow(s, t);
191         if(sumr!=sumc) puts("Impossible");
192         else if(flow1!=sumr) puts("Impossible");
193         else if(!judge_loop()) puts("Not Unique");
194         else{
195             puts("Unique");
196             put();
197         }
198     }
199     return 0;
200 }

原文地址:https://www.cnblogs.com/der-z/p/3877910.html