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

Hdu-4888 Redraw Beautiful Drawings 网络流

2014-07-30 14:43 218 查看
题目链接

我们建一个二部图,左边是行,右边是列,建个源点与行建边,容量是该行的和,列与新建的汇点建边,容量是该列的和,最后每行与每列建边,容量为题意中的k。建边如图:



跑一遍最大流,如果最大流等于行的和且等于列的和,那么就是有解的,否则无解。这样我们得到了一组解,行i到列j的流量即为i行j列的大小。之后便是判断是否有多种情况了。基本思路是这样的,我们看下图:



有多解的情况一定可以找到这样的4个位置:AB同行,CD同行,AC同列,BD同列,并且他们符合一下两种情况的其中一种:

1、AD未达到k(可变大),BC不是0(可减小)

2、AD不是0(可减小),BC未达到k(可变大)

#include "stdio.h"
#include "queue"
#include "iostream"
#include "math.h"
#include "algorithm"
using namespace std;
const int maxn = 1005;
const int mod = 1000000007 ;
const int inf = 1<<30;
const double eps = 1e-8;
typedef __int64 LL;
typedef pair<int,int> pii;
int n,m,K,tot,s,e;
int sum[maxn];
int dis[maxn],vis[maxn],mat[maxn][maxn];
int head[maxn];
struct Node
{
int v,cap,pos,next;
}node[maxn*maxn];
void addedge( int u,int v,int c )
{
node[tot].v = v;   node[tot].cap = c;
node[tot].pos = tot; node[tot].next = head[u];	head[u] = tot ++;

node[tot].v = u;   node[tot].cap = 0;
node[tot].pos = tot; node[tot].next = head[v];	head[v] = tot ++;
}
bool Dinic_Bfs( int st,int end )        //BFS分层
{
memset( vis,0,sizeof(vis) );
memset( dis,0,sizeof(dis) );
queue<int>que;
dis[st] = 0; vis[st] = true;
que.push(st);
while( !que.empty() )
{
int u = que.front();  que.pop();
if( u == end )      //分层到汇点就结束
return true;
for( int i = head[u]; i != -1; i = node[i].next )
{
Node &v = node[i];
if( !vis[v.v] && v.cap )
{
vis[v.v] = true;
dis[v.v] = dis[u] + 1;
que.push( v.v );
}
}
}
return false;
}

int Dinic_Dfs( int st,int maxf,int end )    //沿BFS的分层增广
{
int ans = 0,flow;
if( st == end )
return maxf;
for( int i = head[st]; i != -1; i = node[i].next )
{
Node &v = node[i];
if( v.cap && dis[v.v] == dis[st] + 1 ){
flow = Dinic_Dfs( v.v,v.cap<maxf?v.cap:maxf,end);    //i点能流走的流量
v.cap -= flow;         //增广
node[v.pos^1].cap += flow;
ans += flow;
maxf -= flow;
if( !maxf )
return ans;
}
}
if( !ans )      //注意没得流的时候要标记为-1
dis[st] = -1;
return ans;
}

int Dinic( int st,int end )
{
int ans = 0;
while( Dinic_Bfs(st,end) ){     //分层
ans += Dinic_Dfs( st,inf,end );  //增广
}
return ans;
}
bool dfs( int x,int pre )
{
vis[x] = 1;
for( int i = head[x]; i != -1; i = node[i].next )
{
if(  node[i].v != pre && node[i].cap )
{
if( vis[node[i].v] || dfs( node[i].v,x ) )	return true;
}
}
vis[x] = 0;
return false;
}
bool fun()
{
memset( vis,0,sizeof(vis) );
for( int i = 1; i <= n; i ++ )
{
if( dfs( i,i ) )
return true;
}
return false;
}
void init()
{
tot = 0;
memset( head,-1,sizeof(head) );
}
void Printf()
{
puts("Unique");
for( int i = 1; i <= n; i ++ )
{
for( int j = head[i]; j != -1; j = node[j].next )
{
Node &v = node[j];
if( v.v > n && v.v <= n+m )
mat[i][v.v-n] = K - v.cap;
}
}
for( int i = 1; i <= n; i ++ )
{
for( int j = 1; j <= m; j ++ )
{
printf("%d%c",mat[i][j],j != m?' ':'\n');
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("data.txt","r",stdin);
//freopen("data1.txt","w",stdout);
#endif
while( scanf("%d%d%d",&n,&m,&K) != EOF )
{
init();
int sum1 = 0,sum2 = 0;
s = n+m+1;  e = n+m+2;
for( int i = 1; i <= n; i ++ ){
scanf("%d",&sum[i]);
sum1 += sum[i];
}
for( int i = n+1; i <= n+m; i ++ ){
scanf("%d",&sum[i]);
sum2 += sum[i];
}
if( sum1 != sum2 )
{
puts("Impossible");
continue;
}
for( int i = 1; i <= n; i ++ )
{
addedge( s,i,sum[i] );
for( int j = n+1; j <= n+m; j ++ )
addedge( i,j,K );
}
for( int i = n+1; i <= n+m; i ++ )
addedge( i,e,sum[i] );
int ans = Dinic( s,e );
if( ans != sum1 )
{
puts("Impossible");
}
else if( fun() )
printf("Not Unique\n");
else
{
Printf();
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: