zoukankan      html  css  js  c++  java
  • hdu 4888 Redraw Beautiful Drawings 最大流

    好难好难,将行列当成X和Y,源汇点连接各自的X,Y集,容量为行列的和,相当于从源点流向每一行,然后分配流量给每一列,最后流入汇点,这样执意要推断最后是否满流,就知道有没有解,而解就是每一行流向每一列多少流量。

    关键在于怎么推断多解的情况。我想不到啊T_T

    题讲解,找到一个长度大于2的环。

    想了一想,也就是找到还有剩余流量的环,假设找到了,我就能够把当中一条边的流量转移,由于是一个环,所以它又会达到平衡,不会破坏最大流,可是这样转移后,解就多了一种,所以仅仅要推断是否有一个长度大于2的环就够了。

    这里长度为什么要大于2,由于建图时的反向弧会导致 A->B而且B立马->A,这种话,也是一个环,但转移这条环的流量却会破坏最大流。

    所以我们在用dfs找环的时候,要注意不能立马走反向弧。

    dinic用了当前弧优化。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<string>
    #define eps  1e-12
    #define INF   0x7fffffff
    #define maxn 1005
    using namespace std;
    int n,m,k;
    int en;
    int st,ed;
    int dis[maxn],cur[maxn];
    int que[999999];
    struct edge
    {
        int to,c,next;
    };
    edge e[999999];
    int head[maxn];
    void add(int a,int b,int c)
    {
        e[en].to=b;
        e[en].c=c;
        e[en].next=head[a];
        head[a]=en++;
        e[en].to=a;
        e[en].c=0;
        e[en].next=head[b];
        head[b]=en++;
    }
    int bfs()
    {
        memset(dis,-1,sizeof(dis));
        dis[st]=0;
        int front=0,rear=0;
        que[rear++]=st;
        while(front<rear)
        {
            int j=que[front++];
            for(int k=head[j];k!=-1;k=e[k].next)
            {
                int i=e[k].to;
                if(dis[i]==-1&&e[k].c)
                {
                    dis[i] = dis[j]+ 1 ;
                    que[rear++]=i;
                    if(i==ed) return true;
                }
            }
        }
        return false;
    }
    int dfs(int x,int mx)
    {
        if(x==ed || mx==0) return mx;
        int f,flow=0;
        for(int& i=cur[x];i!=-1;i=e[i].next)
        {
            if(dis[x]+1==dis[e[i].to] && (f=dfs(e[i].to,min(mx,e[i].c))))
            {
                e[i].c-=f;
                e[i^1].c+=f;
                flow+=f;
                mx-=f;
                if(!mx)break;
            }
        }
         return flow;
    }
    
    void init()
    {
        en=0;
        st=0;     //源
        ed=n+m+1;     //汇
        memset(head,-1,sizeof(head));
    }
    inline int ReadInt()
    {
        char ch = getchar();
        int data = 0;
        while (ch < '0' || ch > '9')
        {
            ch = getchar();
        }
        do
        {
            data = data*10 + ch-'0';
            ch = getchar();
        }while (ch >= '0' && ch <= '9');
            return data;
    }
    int s1,s2;
    void build()
    {
        int x,y,z;
        for(int i=1;i<=n;i++)
        {
            x=ReadInt();
            s1+=x;
            add(st,i,x);
        }
        for(int i=1;i<=m;i++)
        {
            x=ReadInt();
            s2+=x;
            add(i+n,ed,x);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                add(i,j+n,k);
            }
        }
    }
    int dinic()
    {
        int tmp=0;
        int maxflow=0;
        while(bfs())
        {
            for(int i=st;i<=ed;i++) cur[i]=head[i];
            while(tmp=dfs(st,INF)) maxflow+=tmp;
        }
        return maxflow;
    }
    int TIME;
    struct node2
    {
        int to,next;
    }e2[999999];
    int en2,head2[maxn];
    void add2(int a,int b)
    {
        e2[en2].to=b;
        e2[en2].next=head2[a];
        head2[a]=en2++;
    }
    bool vis[maxn];
    bool loop(int now,int fa)
    {
        for(int i=head2[now];~i;i=e2[i].next)
        {
            int to=e2[i].to;
            if(to!=fa)
            {
                if(vis[to]) return true;
                vis[to]=1;
                if(loop(to,now)) return true;
                vis[to]=0;
            }
        }
        return false;
    }
    
    bool cal()
    {
        en2=0;
        memset(head2,-1,sizeof(head2));
        for(int i=1;i<=n+m;i++)
        {
            for(int j=head[i];~j;j=e[j].next)
            {
                if(e[j].c&&e[j].to>=1&&e[j].to<=n+m)
                {
                    add2(i,e[j].to);
                }
            }
        }
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            if(loop(i,-1)) return true;
        }
        return false;
    }
    int ans[505];
    int main()
    {
        int ca=1;
        while(scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
            s1=s2=0;
            init();
            build();
            int maxflow=dinic();
            if(maxflow!=s1||s1!=s2) puts("Impossible");
            else
            {
                if(cal()) puts("Not Unique");
                else
                {
                    puts("Unique");
                    for(int i=1;i<=n;i++)
                    {
                        for(int j=head[i];~j;j=e[j].next)
                        {
                            if(e[j].to>n&&e[j].to<=n+m)
                            {
                                ans[e[j].to-n]=k-e[j].c;
                            }
                        }
                        for(int j=1;j<=m;j++)
                        {
                            if(j==1) printf("%d",ans[j]);
                            else printf(" %d",ans[j]);
                        }
                        puts("");
                    }
                }
            }
        }
    }
    


  • 相关阅读:
    二维数组问题
    如何在Windows环境下寻找并杀死进程
    关于使用YYYY-MM-dd产生BUG的问题
    boolean在Java中占几个字节的问题
    IDEA启动项目时报错:Error running 'Application': Command line is too long. Shorten command line for Application or also for Spring Boot default configuration.
    mvn package失败,不再支持源选项 1.5。请使用 1.6 或更高版本。
    17蓝桥杯竞赛题“购物单”
    17蓝桥杯竞赛题“取数位”
    微信公众平台开发(ASP.NET)
    宋艳杰个人作品集合
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3930319.html
Copyright © 2011-2022 走看看