模版如下://HDU 4888:http://acm.hdu.edu.cn/showproblem.php?pid=4888
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; #define ll __int64 #define eps 1e-8 const ll Mod=(1e9+7); const int maxn = 510; const int maxm = 50100; int n,m,k; int r[maxn],c[maxn]; int ma[maxn][maxn]; const int maxnode = 1000 + 5; const int maxedge = 2*161000 + 5; const int oo = 1000000000; int node, src, dest, nedge; int head[maxnode], point[maxedge], next1[maxedge], flow[maxedge], capa[maxedge];//point[x]==y表示第x条边连接y,head,next为邻接表,flow[x]表示x边的动态值,capa[x]表示x边的初始值 int dist[maxnode], Q[maxnode], work[maxnode];//dist[i]表示i点的等级 void init(int _node, int _src, int _dest){//初始化,node表示点的个数,src表示起点,dest表示终点 node = _node; src = _src; dest = _dest; for (int i = 0; i < node; i++) head[i] = -1; nedge = 0; } void addedge(int u, int v, int c1, int c2){//增加一条u到v流量为c1,v到u流量为c2的两条边 point[nedge] = v, capa[nedge] = c1, flow[nedge] = 0, next1[nedge] = head[u], head[u] = (nedge++); point[nedge] = u, capa[nedge] = c2, flow[nedge] = 0, next1[nedge] = head[v], head[v] = (nedge++); } bool dinic_bfs(){ memset(dist, 255, sizeof (dist)); dist[src] = 0; int sizeQ = 0; Q[sizeQ++] = src; for (int cl = 0; cl < sizeQ; cl++) for (int k = Q[cl], i = head[k]; i >= 0; i = next1[i]) if (flow[i] < capa[i] && dist[point[i]] < 0){ dist[point[i]] = dist[k] + 1; Q[sizeQ++] = point[i]; } return dist[dest] >= 0; } int dinic_dfs(int x, int exp){ if (x == dest) return exp; for (int &i = work[x]; i >= 0; i = next1[i]){ int v = point[i], tmp; if (flow[i] < capa[i] && dist[v] == dist[x] + 1 && (tmp = dinic_dfs(v, min(exp, capa[i] - flow[i]))) > 0){ flow[i] += tmp; flow[i^1] -= tmp; return tmp; } } return 0; } int dinic_flow(){ int result = 0; while (dinic_bfs()){ for (int i = 0; i < node; i++) work[i] = head[i]; while (1){ int delta = dinic_dfs(src, oo); if (delta == 0) break; result += delta; } } return result; } //建图前,运行一遍init(); //加边时,运行addedge(a,b,c,0),表示点a到b流量为c的边建成(注意点序号要从0开始) //求解最大流运行dinic_flow(),返回值即为答案 bool judge(int sumrow){ int flow = 1; for(int i = 1;i <= n;i++) for(int j = n+1;j <= n+m;j ++) addedge(i,j,k,0); flow=dinic_flow(); if(flow != sumrow) return false; return true; } int main() { //k为能填原图能填的数字的最大值 while(scanf("%d%d%d",&n,&m,&k) != EOF){ init(n+m+2,0,n+m+1); int flag = 0; int sumrow = 0,colrow = 0; for(int i = 1;i <= n;i++){ scanf("%d",&r[i]); addedge(0,i,r[i],0); sumrow += r[i]; if(r[i]<0 || r[i]>m*k) flag = 1; } for(int j = 1;j <= m;j ++){ scanf("%d",&c[j]); addedge(j+n,n+m+1,c[j],0); colrow += c[j]; if(c[j]<0 || c[j]>n*k) flag = 1; } if(sumrow != colrow){ printf("Impossible\n"); continue; } if(!judge(sumrow)) flag = 1; if(flag == 1){ printf("Impossible\n"); continue; } memset(ma,-1,sizeof(ma)); int i,j; for(i=1;i<=n;i++) if(r[i]==0) for(j=1;j<=m;j++) ma[i][j]=0; for(j=1;j<=m;j++) if(c[j]==0) for(i=1;i<=n;i++) ma[i][j]=0; int tt=2; int sum,num,temp; while(tt--) { for(i=1;i<=n;i++) { if(r[i]==0) { for(j=1;j<=m;j++) if(ma[i][j]==-1) ma[i][j]=0; continue; } sum=0; num=0; for(j=1;j<=m;j++) { if(ma[i][j]==-1) { num++; temp=j; sum+=min(k,c[j]); } } if(num==1) { ma[i][temp]=r[i]; r[i]-=ma[i][temp]; c[temp]-=ma[i][temp]; continue; } else if(sum==r[i]) { for(j=1;j<=m;j++) { if(ma[i][j]==-1) { ma[i][j]=min(k,c[j]); r[i]-=ma[i][j]; c[j]-=ma[i][j]; } } } } for(j=1;j<=m;j++) { if(c[j]==0) { for(i=1;i<=n;i++) if(ma[i][j]==-1) ma[i][j]=0; continue; } sum=0; num=0; for(i=1;i<=n;i++) { if(ma[i][j]==-1) { num++; temp=i; sum+=min(k,r[i]); } } if(num==1) { ma[temp][j]=c[j]; r[temp]-=ma[temp][j]; c[j]-=ma[temp][j]; continue; } else if(sum==c[j]) { for(i=1;i<=n;i++) { if(ma[i][j]==-1) { ma[i][j]=min(k,r[i]); r[i]-=ma[i][j]; c[j]-=ma[i][j]; } } } } } flag=0; for(i=1;i<=n;i++) if(r[i]!=0) { flag=1; break; } for(j=1;j<=m;j++) if(c[j]!=0) { flag=1; break; } if(flag==1) printf("Not Unique\n"); else { printf("Unique\n"); for(i=1;i<=n;i++) { for(j=1;j<m;j++) printf("%d ",ma[i][j]); printf("%d\n",ma[i][m]); } } } return 0; }
时间: 2024-11-09 06:03:48