首页 > 代码库 > hdu4888 Redraw Beautiful Drawings(最大流)

hdu4888 Redraw Beautiful Drawings(最大流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4888

题意:给一个矩阵没行的和和每列的和,问能否还原矩阵,如果可以还原解是否唯一,若唯一输出该矩阵。

思路:设一个源点和汇点,每行的和和源点加边,权值为该行的和,每列的和和汇点加点,权值为该列的和。

   每行和每列加边, 权值为k,跑最大流,如果满流(从源点流出的等于流入汇点的)则证明可以还原该矩阵。

     判断是否有多节,就dfs搜,看残余网络中是否有环,无环则解唯一。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int oo=1e9;
const int mm=4e5+5;
const int mn=1e5+5;

int node,src,dest,edge;
int ver[mm],flow[mm],Next[mm];
int head[mn],work[mn],dis[mn],q[mn];

int Min(int a,int b)
{
    return a<b?a:b;
}

void prepare(int _node,int _src,int _dest)
{
    node=_node,src=http://www.mamicode.com/_src,dest=_dest;
    for(int i=0; i<node; ++i)head[i]=-1;
    edge=0;
}


void Addedge(int u,int v,int c)
{
    ver[edge]=v,flow[edge]=c,Next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,Next[edge]=head[v],head[v]=edge++;
}

bool Dinic_bfs()
{
    int i,u,v,l,r=0;
    for(i=0; i<node; ++i)dis[i]=-1;
    dis[q[r++]=src]=0;
    for(l=0; l<r; ++l)
        for(i=head[u=q[l]]; i>=0; i=Next[i])
            if(flow[i]&&dis[v=ver[i]]<0)
            {
                dis[q[r++]=v]=dis[u]+1;
                if(v==dest)return 1;
            }
    return 0;
}

int Dinic_dfs(int u,int exp)
{
    if(u==dest)return exp;
    for(int &i=work[u],v,tmp; i>=0; i=Next[i])
        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,Min(exp,flow[i])))>0)
        {
            flow[i]-=tmp;
            flow[i^1]+=tmp;
            return tmp;
        }
    return 0;
}

int Dinic_flow()
{
    int i,ret=0,delta;
    while(Dinic_bfs())
    {
        for(i=0; i<node; ++i) work[i]=head[i];
        while(delta=Dinic_dfs(src,oo)) ret+=delta;
    }
    return ret;
}

int n,m,k;
int vit[500005];
int mp[505][505];

int dfs(int u,int p)
{
    if(vit[u]) return 1;
    vit[u]=1;
    for(int i=head[u]; i!=-1; i=Next[i])
    {
        int v=ver[i];
        if(v!=p && v!=0 && v!=(n+m+1) && flow[i])
            if(dfs(v,u)) return 1;
    }
    vit[u]=0;
    return 0;
}

int main()
{
    while(scanf("%d%d%d",&n,&m,&k)==3)
    {
        prepare(n+m+2,0,n+m+1);
        int sum1=0,sum2=0;
        int x;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&x);
            sum1+=x;
            Addedge(0,i,x);
            for(int j=1; j<=m; j++)
                Addedge(i,j+n,k);
        }
        for(int i=1; i<=m; i++)
        {
            scanf("%d",&x);
            Addedge(i+n,n+m+1,x);
            sum2+=x;
        }
        int ans=Dinic_flow();

        if(ans==sum1 && ans==sum2)
        {
            int flag=0;
            memset(vit,0,sizeof(vit));
            for(int i=1; i<=n; i++)
            {
                memset(vit,0,sizeof(vit));
                if(dfs(i,-1))
                {
                    flag=1;
                    break;
                }
            }
            if(flag) puts("Not Unique");
            else
            {
                puts("Unique");
                memset(mp,0,sizeof(mp));
                for(int i=1; i<=n; i++)
                {
                    for(int j=head[i]; j!=-1; j=Next[j])
                    {
                        int v=ver[j];
                        if(v>n && v<=n+m)
                            mp[i][v-n]=k-flow[j];
                    }
                }
                for(int i=1; i<=n; i++)
                {
                    for(int j=1; j<=m; j++)
                    {
                        if(j!=1)
                            printf(" ");
                        printf("%d",mp[i][j]);

                    }
                    puts("");
                }
            }

        }
        else puts("Impossible");
    }
    return 0;
}

 

hdu4888 Redraw Beautiful Drawings(最大流)