hdu4888 Redraw Beautiful Drawings(最大流)

Posted a_clown_cz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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=_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(最大流)的主要内容,如果未能解决你的问题,请参考以下文章

hdu4872 Beautiful Soup 模拟

hdu 4781 Beautiful Soup 构造

HDU 4782 Beautiful Soup(模拟)

HDU 5321 Beautiful Set 容斥 (看题解)

HDU5179 beautiful number 题解 数位DP

HDU 5179 beautiful number (数位dp / 暴力打表 / dfs)