hdu 4888 Redraw Beautiful Drawings 最大流唯一性判断

//n*m的矩阵
//给出n行每行的所有数之和
//给出m列中每列的所有数之和
//每个格子的数x 0 <= x <= k
//问能不能构成矩阵 , 这个矩阵是否唯一确定
//判断最大流是否唯一确定是
//在残余网络看能不能找到一个环 , 如果能找到那么最大流
//可以沿着这个环走一遍而不改变最大流
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std ;
const int maxn = 1010 ;
const int maxm = 410*410  ;
const int inf = 0x7fffffff ;
int st = 0 ; int en = 1001 ;
int vis[maxn] ;
int head[maxn] ;
int dis[maxn]  ;
int q[maxn];
int nedge  = 0 ;
int ma[maxn][maxn] ;
struct Edge
{
    int v ;int next;
    int w ;
}edge[maxm<<1] ;
void addedge(int u , int v , int w)
{
    edge[nedge].v = v ;
    edge[nedge].w = w ;
    edge[nedge].next = head[u] ;
    head[u] = nedge++ ;
    edge[nedge].v = u ;
    edge[nedge].w = 0 ;
    edge[nedge].next = head[v] ;
    head[v] = nedge++ ;
}
bool bfs()
{
    memset(dis , -1 ,sizeof(dis)) ;
    int front = 0 , tear = 0 ;
    dis[st] = 0 ;
    q[tear++] = st;
    while(front < tear)
    {
        int u = q[front++] ;
        for(int i = head[u]; i != -1 ; i = edge[i].next)
        {
            int v = edge[i].v ;
            if(edge[i].w > 0 && dis[v] < 0)
            {
                dis[v] = dis[u] + 1 ;
                q[tear++] = v ;
            }
        }
    }
    if(dis[en] > 0)
    return true ;
    return false ;
}
int dfs(int x,int mx)
{
    if(x==en)
    return mx;;
    int ans=0;
    int a;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(dis[v]==dis[x]+1&&edge[i].w>0&&(a=dfs(v,min(mx,edge[i].w))))
        {
            edge[i].w -= a;
            edge[i^1].w += a;
            ans += a;
            mx -= a;
            if(!mx)
            break;
        }
    }
    if(!ans)
    dis[x] = -1;
    return ans;
}
bool dfss(int u , int pre)
{
    for(int i = head[u] ;i != -1; i = edge[i].next)
    {
        int v = edge[i].v ;
        if(v == pre || !edge[i].w || v == st || v == en)continue ;
        if(vis[v])
          return true ;
        vis[v] = 1;
        if(dfss(v , u))
          return true ;
        vis[v] = 0 ;
    }
    return false   ;
}
int main()
{
  // freopen("in.txt" , "r" , stdin)  ;
    int n , m , k;
    while(~scanf("%d%d%d" , &n , &m , &k))
    {
        memset(head , -1 , sizeof(head)) ;
        memset(vis , 0 , sizeof(vis)) ;
        nedge = 0 ;
        int sum1 = 0 ;
        int sum2 = 0 ;
        st = 0 , en = n + m + 1 ;
        for(int i = 1;i <= n;i++)
        {
            int t  ;
            scanf("%d" , &t) ;
            sum1 += t ;
            addedge(st , i , t) ;
            for(int j = 1;j <= m;j++)
            addedge(i , j + n , k) ;
        }
        for(int j = 1;j <= m;j++)
        {
            int t  ;
            scanf("%d" , &t) ;
            sum2 += t ;
            addedge(j + n , en , t)  ;
        }
        int ans = 0 ;
        int res ;
        if(sum1 != sum2)
        {
            puts("Impossible") ;
            continue ;
        }
        while(bfs())
          while(res = dfs(st , inf))
           ans += res ;
        if(ans != sum1)
        {
            puts("Impossible") ;
            continue ;
        }
        bool flag = false ;
        for(int i = 0;i <= n;i++)
        if(dfss(i , -1))
        {
            flag = true ;
            break ;
        }
        if(flag)
        {
            puts("Not Unique") ;
            continue ;
        }
        puts("Unique") ;
        for(int i = 1;i <= n;i++)
          for(int j = head[i] ; j != -1 ;j = edge[j].next)
          if(edge[j].v > n && edge[j].v <= n + m)
          ma[i][edge[j].v - n] = edge[j^1].w ;
        for(int i = 1;i <= n;i++)
          for(int j = 1;j <= m;j++)
          printf("%d%c" , ma[i][j] , j == m?'\n':' ') ;
    }
    return  0 ;
}






















































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值