zoukankan      html  css  js  c++  java
  • hdu 4888 最大流慢板

    http://acm.hdu.edu.cn/showproblem.php?pid=4888

    添加一个源点与汇点,建图如下:
    1. 源点 -> 每一行对应的点,流量限制为该行的和
    2. 每一行对应的点 -> 每一列对应的点,流量限制为 K
    3. 每一列对应的点 -> 汇点,流量限制为该列的和
    求一遍最大流,若最大流与矩阵之和相等,说明有解,否则无解。判断唯一解,是判断残量网络中是否存在一个长度大于2的环,若存在说明有多解,否则有唯一解,解就是每条边行i->列j的流量。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <cstdlib>
    using namespace std;
    
    const int maxn=500,maxm=maxn*maxn;
    int next[maxm*2],num[maxm*2],r[maxm*2],a[maxn*2],row_sum[maxn],col_sum[maxn],n,m,K,tt,T,d[maxn*2],st[maxn*2],cod[maxn][maxn];
    int h[maxn*2],vh[maxn*2];
    bool don[maxm*2],in[maxn*2];
    
    
    void insert(int x,int y,int rr)
    {
        next[++tt]=a[x];num[tt]=y;r[tt]=rr;a[x]=tt;
        next[++tt]=a[y];num[tt]=x;r[tt]=0;a[y]=tt;
    }
    
    void construct()
    {
        tt=1;T=n+m+1;
        for (int i=0;i<=T;i++) a[i]=0;
        for (int i=1;i<=n;i++) insert(0,i,row_sum[i]);
        for (int i=1;i<=m;i++) insert(i+n,T,col_sum[i]);
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=m;j++)
            {
                insert(i,j+n,K);
                cod[i][j]=tt;
            }
        }
    }
    
    int dfs(int x,int y)
    {
        if (x==T) return y;
        int sig=st[x],minh=T+1;
        do
        {
            if (r[st[x]])
            {
                if (h[num[st[x]]]+1==h[x])
                {
                    int k=dfs(num[st[x]],min(y,r[st[x]]));
                    if (k)
                    {
                        r[st[x]]-=k;
                        r[st[x]^1]+=k;
                        return k;
                    }
                }
                minh=min(minh,h[num[st[x]]]+1);
                if (h[0]>T) return 0;
            }
            st[x]=next[st[x]];
            if (st[x]==0) st[x]=a[x];
        }while (sig!=st[x]);
        if (vh[h[x]]--==0) h[0]=T+1;
        vh[h[x]=minh]++;
        return 0;
    }
    
    int max_flow()
    {
        for (int i=0;i<=T;i++) h[i]=vh[i]=0;
        for (int i=0;i<=T;i++) st[i]=a[i];
        vh[0]=T+1;
        int ret=0;
        while (h[0]<=T) ret+=dfs(0,K+1);
        return ret;
    }
    
    /*bool find_circle()
    {
        deque <int> q;
        for (int i=0;i<=T;i++) d[i]=0;
        for (int i=0;i<=T;i++)
        {
            for (int p=a[i];p;p=next[p])
            {
                if (r[p]) d[i]++;
            }
            if (d[i]==0) q.push_back(i);
        }
        int cnt=T+1;
        while (!q.empty())
        {
            int x=q.front();
            cnt--;
            q.pop_front();
            for (int p=a[x];p;p=next[p])
            {
                if (r[p^1]) 
                {
                    d[num[p]]--;
                    if (d[num[p]]==0) q.push_back(num[p]);
                }
            }
        }
        return cnt;
    }*/
    
    bool visit(int x,int ed)
    {
        if (don[ed]) 
            return in[x];
        don[ed]=true;
        in[x]=true;
        for (int p=a[x];p;p=next[p])
        {
            if (r[p] && (ed^p)!=1)
                if (visit(num[p],p)) return true;
        }
        in[x]=false;
        return false;
    }
    
    bool find_circle()
    {
        for (int i=0;i<=T;i++) in[i]=false;
        for (int i=1;i<=tt;i++) don[i]=false;
        int col=0;
        for (int i=2;i<=tt;i++)
        {
            if (r[i] && !don[i])
            {
                in[num[i^1]]=true;
                if (visit(num[i],i)) return true; 
                in[num[i^1]]=false;
            }
        }
        return false;
    }
    
    void print_scheme()
    {
        printf("Unique
    ");
        for (int i=1;i<=n;i++)
        {
            printf("%d",r[cod[i][1]]);
            for (int j=2;j<=m;j++) printf(" %d",r[cod[i][j]]);
            printf("
    ");
        }
    }
    
    int main()
    {
        while (scanf("%d%d%d",&n,&m,&K)!=EOF)
        {
            int tmp=0;
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&row_sum[i]);
                tmp+=row_sum[i];
            }
            int sum=tmp;
            for (int i=1;i<=m;i++)
            {
                scanf("%d",&col_sum[i]);
                tmp-=col_sum[i];
            }
            if (tmp) 
            {
                printf("Impossible
    ");
                continue;
            }
            construct();
            if (max_flow()<sum)
            {
                printf("Impossible
    ");
                continue;
            }
            if (find_circle())
            {
                printf("Not Unique
    ");
            }else print_scheme();
        }
        
    
        return 0;
    }


  • 相关阅读:
    emulate sh
    postmaster.c 中的 ListenAddresses
    PostgreSQL的postmaster的fork动作验证
    NotifyMyFrontEnd 函数背后的数据缓冲区(三)
    对${ZSH_VERSION+set}的验证
    微软正准备一个简易的Rootkit清除方案 助用户打补丁 狼人:
    创新与安全:云计算的两只跷跷板 狼人:
    苹果禁止iPhone黑客访问App Store应用商店 狼人:
    春节不回家 单身留守族“拼饭”“拼玩” 狼人:
    僵尸侵入全球 袭击者或为东欧黑帮 狼人:
  • 原文地址:https://www.cnblogs.com/zibaohun/p/4046805.html
Copyright © 2011-2022 走看看