题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4888
题目大意:题意:给一个n*m的矩形,往每个格子填0-k的数字,使得对第i行和为row[i],第i列和为col[i],问是否存在方案,方案是否唯一,如果方案唯一则输出具体方案。
建图:源点和每行连边,容量为每行的和。每列和汇点连边,容量为每列的和。每行和每列连边,容量为k。
判断是否存在唯一解,在残留网络里面能否找到一个环。
#include <bits/stdc++.h>
using namespace std;
const int maxm=400000;
const int maxn=1000;
const int inf=0x3f3f3f3f;
struct node{
int u;
int to;
int flow;
int next;
}e[maxm];
int start,tend,cut;
int head[maxn],work[maxn],dis[maxn],q[maxn];
inline void addcut(int u,int v,int c1)
{
e[cut].u=u; e[cut].to=v,e[cut].flow=c1,e[cut].next=head[u],head[u]=cut++;
e[cut].u=v; e[cut].to=u,e[cut].flow=0, e[cut].next=head[v],head[v]=cut++;
}
bool Dinic_bfs()
{
int i,u,v,l,r=0;
memset(dis, -1, sizeof(dis));
dis[q[r++]=start]=0;
for(l=0;l<r;++l)
for(i=head[u=q[l]];i>=0;i=e[i].next)
if(e[i].flow&&dis[v=e[i].to]<0)
{
dis[q[r++]=v]=dis[u]+1;
if(v==tend)return 1;
}
return 0;
}
int Dinic_dfs(int u,int exp)
{
if(u==tend)return exp;
for(int &i=work[u],v,tmp;i>=0;i=e[i].next)
if(e[i].flow&&dis[v=e[i].to]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,e[i].flow)))>0)
{
e[i].flow-=tmp;
e[i^1].flow+=tmp;
return tmp;
}dis[u]--;
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
//改板子 保证访问到所有点
/*************************/
for(i=start;i<=tend;++i)work[i]=head[i];
/**************************/
while(delta=Dinic_dfs(start,inf))ret+=delta;
}
return ret;
}
int mp[500][500];
int mark[2000];
bool dfs(int u,int fa)
{
if(mark[u]==true){
return true;
}
int biu=-1;
mark[u]=true;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v==fa){
biu=i;//这句话必须加,不加4975可以做 4888做不了
continue;
}
if(e[i].flow>0){
if(dfs(v,u)){
return true;
}
}
if(biu==-1){
head[u]=e[i].next;
}
else{
e[biu].next=e[i].next;
}
biu=i;
}
mark[u]=false;
return false;
}
bool judge(int n)
{
memset(mark,false,sizeof(mark));
for(int i=0;i<=n;i++)
if(dfs(i,-1))return true;
return false;
}
int main()
{
int n, m, k, T;
while(scanf("%d%d%d", &n, &m, &k)!=EOF)
{
int x, sum1=0, sum2=0;
cut=0;
memset(head, -1, sizeof(head));
for(int i=1; i<=n; i++){
scanf("%d", &x);
sum1+=x;
addcut(0, i, x);
}
for(int i=1; i<=m; i++){
scanf("%d", &x);
sum2+=x;
addcut(n+i, n+m+1, x);
}
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
addcut(i, n+j, k);
}
}
start=0;tend=n+m+1;
int max_s=Dinic_flow();
if(max_s!=sum1||sum1!=sum2){
printf("Impossible\n");
}
else{
if(n==1||m==1||!judge(n+m+1)){
for(int i=1; i<=cut; i+=2){
if(e[i].to<=n&&e[i].to>=1&&e[i].u-n<=m&&e[i].u-n>=0)
mp[e[i].to][e[i].u-n]=e[i].flow;
}
printf("Unique\n");
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
printf("%d%c", mp[i][j], j==m?'\n':' ');
}
}
}
else{
printf("Not Unique\n");
}
}
}
return 0;