Hdu-4888 Redraw Beautiful Drawings 网络流

来源:互联网 发布:交友网站源码 编辑:程序博客网 时间:2024/05/19 12:25

题目链接


我们建一个二部图,左边是行,右边是列,建个源点与行建边,容量是该行的和,列与新建的汇点建边,容量是该列的和,最后每行与每列建边,容量为题意中的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);  #endifwhile( 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;}


0 0
原创粉丝点击