您的位置:首页 > 理论基础 > 计算机网络

hdu 4888 Redraw Beautiful Drawings 2014多校三补题 网络流

2014-08-22 21:42 417 查看
题目链接:hdu 4888

给定一个N*M的矩阵,已知每行和以及每列和,每个元素(大于等于0)的上限值K,问这样的矩阵是否存在,若存在,判断是否唯一,唯一则输出

网络流,从源点向行带表的点建边,流量为行和,列代表的边向汇点建边,流量为列和,每行向每列建边,流量为K,求源点到汇点的最大流,若是满流,则说明矩阵存在。然后判断残留网络是否存在环,若存在则说明有多解

/******************************************************
* File Name:   4888.cpp
* Author:      kojimai
* Creater Time:2014年08月22日 星期五 00时58分29秒
******************************************************/
/*
*网络流,求最大流是否满流
*然后判断残留网络是否存在环
*/
#include<queue>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,K;
#define FFF 404
int row[FFF],col[FFF];
int map[FFF][FFF];
struct node
{
int u,v,f,next;
}p[400010];
int first[900],e,cur[900],dis[900],que[2100];
void addedge(int u,int v,int c)
{
p[e].u=u;p[e].v=v;p[e].f=c;p[e].next=first[u];first[u]=e++;
p[e].u=v;p[e].v=u;p[e].f=0;p[e].next=first[v];first[v]=e++;
}
bool bfs(int s,int t)//找增广路径
{
memset(dis,-1,sizeof(dis));
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty())
{
int now=q.front();q.pop();
for(int k=first[now];~k;k=p[k].next)
{
if(p[k].f>0&&dis[p[k].v]==-1)
{
dis[p[k].v]=dis[now]+1;
if(p[k].v==t)
return true;
q.push(p[k].v);
}
}
}
return false;
}
int dinic(int s,int t)//dinic求最大流
{
//cout<<"s="<<s<<" t="<<t<<endl;
int ans=0;
while(bfs(s,t))
{
memcpy(cur,first,sizeof(first));
int now=s,tail=0;
while(true)
{
int k;
if(now==t)
{
int flow=23333333,fir;
for(int i=0;i<tail;i++)
{
if(p[que[i]].f<flow)
{
fir=i;
flow=p[que[i]].f;
}
}
for(int i=0;i<tail;i++)
{
p[que[i]].f-=flow;
p[que[i]^1].f+=flow;
}
ans+=flow;
tail=fir;
now=p[que[fir]].u;
}
for(k=cur[now];~k;cur[now]=k=p[k].next)
{
if(p[k].f&&dis[now]+1==dis[p[k].v])
break;
}
if(cur[now]!=-1)
{
que[tail++]=cur[now];
now=p[cur[now]].v;
}
else
{
if(tail==0)
break;
dis[now]=-1;
now=p[que[--tail]].u;
}
}
}
return ans;
}
int vis[FFF*2];
/*int dfn[FFF*2],low[FFF*2],c[FFF*2],snum,dnum,stack[FFF*2];
bool tarjan(int s,int last)//tarjan找环不可行,因为不能算两点的环,容易出错
{
dfn[s]=low[s]=dnum++;
stack[snum++]=s;vis[s]=true;
for(int k=first[s];k!=-1;k=p[k].next)
{
//cout<<" s="<<s<<" k="<<k<<" v="<<p[k].v<<" f="<<p[k].f<<endl;
if(p[k].f>0&&k!=last)
{
if(!dfn[p[k].v])
{
if(tarjan(p[k].v,s))
return true;
low[s]=min(low[s],low[p[k].v]);
}
else if(vis[p[k].v])
{
low[s]=min(low[s],dfn[p[k].v]);
}
}
}
//cout<<"s="<<s<<" low="<<low[s]<<" dfn="<<dfn[s]<<endl;
if(low[s]==dfn[s])
{
int y=stack[--snum];
//cout<<"s="<<s<<" y="<<y<<endl;
vis[y]=false;
if(y!=s)
return true;
}
return false;
}*/
bool dfs(int s,int last)//找环
{
for(int k=first[s];~k;k=p[k].next)
{
if(p[k].v==last)continue;
if(p[k].f)
{
if(vis[p[k].v])return true;
vis[p[k].v]=true;
if(dfs(p[k].v,s))return true;
vis[p[k].v]=false;
}
}
return false;
}
void out()
{
printf("Unique\n");
memset(map,0,sizeof(map));
for(int i=1;i<=n;i++)
{
for(int k=first[i];~k;k=p[k].next)
{
if(p[k].v>n&&p[k].v<=n+m)
map[i][p[k].v-n]=K-p[k].f;//用流量上限减去残留网络的值,即为当前的流量
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(j==m)
printf("%d\n",map[i][j]);
else
printf("%d ",map[i][j]);
}
}
return;
}
int main()
{
//freopen("out.out","w",stdout);
while(~scanf("%d%d%d",&n,&m,&K))
{
int alla=0,allb=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&row[i]);
alla+=row[i];
}
for(int i=1;i<=m;i++)
{
scanf("%d",&col[i]);
allb+=col[i];
}
if(alla!=allb)
printf("Impossible\n");
else
{
e=0;
memset(first,-1,sizeof(first));
for(int i=1;i<=n;i++)
{
addedge(0,i,row[i]);
}
for(int i=1;i<=m;i++)
addedge(i+n,n+m+1,col[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
addedge(i,j+n,K);
}
int sum=dinic(0,n+m+1);
if(sum!=alla)
printf("Impossible\n");
else
{
//snum=1;dnum=1;
memset(vis,false,sizeof(vis));
bool flag=false;
//memset(dfn,0,sizeof(dfn));
//memset(low,0,sizeof(low));
for(int i=n;i>=1&&!flag;i--)
{
if(!vis[i])
flag=dfs(i,-1);
}
if(flag)
printf("Not Unique\n");
else
out();
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: