最大流判断多解
建图:
源点连接到每一个代表行的节点容量为行总和,每一个代表列的节点连接到汇点容量为列总和,行和列之间互相连接容量为Limit
多解:
做一遍ISAP后,在残量图上DFS看能否找到点数大于2的环即可
2 2 4 4 2 4 2 4 2 2 2 2 5 0 5 4 1 4 3 9 1 2 3 3
Not Unique Impossible Unique 1 2 3 3
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=1000; const int maxm=1001000; const int INF=0x3f3f3f3f; struct Edge { int to,next,cap,flow; }edge[maxm]; int Size,Adj[maxn]; int gap[maxn],dep[maxn],pre[maxn],cur[maxn]; void init() { Size=0; memset(Adj,-1,sizeof(Adj)); } void addedge(int u,int v,int w,int rw=0) { edge[Size].to=v; edge[Size].cap=w; edge[Size].next=Adj[u]; edge[Size].flow=0;Adj[u]=Size++; edge[Size].to=u; edge[Size].cap=rw; edge[Size].next=Adj[v]; edge[Size].flow=0;Adj[v]=Size++; } int sap(int start,int end,int N) { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,Adj,sizeof(Adj)); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while(dep[start]<N) { if(u==end) { int Min=INF; for(int i=pre[u];~i;i=pre[edge[i^1].to]) if(Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for(int i=pre[u];~i;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for(int i=cur[u];~i;i=edge[i].next) { v=edge[i].to; if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if(flag) { u=v; continue; } int Min=N; for(int i=Adj[u];~i;i=edge[i].next) if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if(u!=start) u=edge[pre[u]^1].to; } return ans; } int n,m,limit; int a[maxn],b[maxn]; int id[maxn][maxn]; bool vis[maxn]; bool dfs(int u,int pre) { if(vis[u]) return true; vis[u]=true; for(int i=Adj[u];~i;i=edge[i].next) { int v=edge[i].to; if(edge[i].flow>=edge[i].cap) continue; if(v==pre) continue; if(dfs(v,u)) return true; } vis[u]=false; return false; } int main() { while(scanf("%d%d%d",&n,&m,&limit)!=EOF) { init(); int sum1=0,sum2=0; for(int i=1;i<=n;i++) scanf("%d",a+i),sum1+=a[i]; for(int i=1;i<=m;i++) scanf("%d",b+i),sum2+=b[i]; if(sum1!=sum2) { puts("Impossible"); continue; } /**************build graph *****************/ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { id[i][j]=Size; addedge(i,n+j,limit); } for(int i=1;i<=n;i++) addedge(0,i,a[i]); for(int i=1;i<=m;i++) addedge(n+i,n+m+1,b[i]); /**************build graph *****************/ int MaxFlow=sap(0,n+m+1,n+m+1+2); //cout<<"MaxFlow: "<<MaxFlow<<endl; if(MaxFlow!=sum1) { puts("Impossible"); continue; } else { memset(vis,0,sizeof(vis)); bool flag=false; for(int i=1;i<=n&&!flag;i++) if(dfs(i,i)) flag=true; if(flag) { puts("Not Unique"); continue; } puts("Unique"); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { printf("%d%c",edge[id[i][j]].flow,(j==m)?10:32); } } } return 0; }