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\n",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 }