点击打开链接
题意:给定NxM的矩阵,每个点的元素在0~k之间,然后每行元素的和,每列元素的和,问能否有情况使条件符合
思路:建个源点,与每行建一条流量为行和的边,每一列与汇点建一条流量为列和的边,每行与每列建一条流量为9的边,跑最大流后判断是否满流就行了,但是要怎么判断有没有多组解呢,当残余网络中有环时,我们可以调整这个环来符合条件,将一条边加1,则另一条边可以减去1,所以判断残余网络中有没有大于2的环,现将流量大于0的边预处理出来,然后dfs求有没有环,与hdu4975相似
#include <queue> #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> #include <functional> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int maxn=1010; struct edge{ int to,cap,rev; edge(int a,int b,int c){to=a;cap=b;rev=c;} }; vector<edge>G[maxn]; vector<int>G1[maxn]; int level[maxn],iter[maxn],vis[maxn],n,m; void addedge(int from,int to,int cap){ G[from].push_back(edge(to,cap,G[to].size())); G[to].push_back(edge(from,0,G[from].size()-1)); } void add_edge(int from,int to){ G1[from].push_back(to); } void bfs(int s){ memset(level,-1,sizeof(level)); queue<int>que;level[s]=0; que.push(s); while(!que.empty()){ int v=que.front();que.pop(); for(unsigned int i=0;i<G[v].size();i++){ edge &e=G[v][i]; if(e.cap>0&&level[e.to]<0){ level[e.to]=level[v]+1; que.push(e.to); } } } } int dfs(int v,int t,int f){ if(v==t) return f; for(int &i=iter[v];i<G[v].size();i++){ edge &e=G[v][i]; if(e.cap>0&&level[v]<level[e.to]){ int d=dfs(e.to,t,min(f,e.cap)); if(d>0){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int max_flow(int s,int t){ int flow=0; while(1){ bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,inf))>0) flow+=f; } } bool Judge_dfs(int x,int val){ vis[x]=1; for(unsigned int i=0;i<G1[x].size();i++){ int t=G1[x][i]; if(t==val) continue; if(vis[t]) return 1; if(Judge_dfs(t,x)) return 1; } vis[x]=0; return 0; } bool judge(){ memset(vis,0,sizeof(vis)); for(int i=0;i<=n+m+1;i++){ for(unsigned int j=0;j<G[i].size();j++){ edge &e=G[i][j]; if(e.cap>0) add_edge(i,e.to); } } for(int i=0;i<=n;i++){ if(Judge_dfs(i,-1)) return 1; } return 0; } int main(){ int T,a,b,k; while(scanf("%d%d%d",&n,&m,&k)!=-1){ for(int i=0;i<maxn;i++){ G[i].clear(); G1[i].clear(); } int sum=0,sum1=0,sum2=0; for(int i=1;i<=n;i++){ scanf("%d",&a);sum+=a;sum1+=a; addedge(0,i,a); } for(int j=1;j<=m;j++){ scanf("%d",&b);sum2+=b; addedge(j+n,n+m+1,b); } if(sum1!=sum2){ printf("Impossible\n"); continue; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) addedge(i,j+n,k); } int ans=max_flow(0,n+m+1); if(ans!=sum) printf("Impossible\n"); else{ if(judge()) printf("Not Unique\n"); else{ printf("Unique\n"); for(int i=1;i<=n;i++){ for(int j=1;j<m;j++){ printf("%d ",k-G[i][j].cap); } printf("%d\n",k-G[i][m].cap); } } } } return 0; }