• ZOJ1994有源汇上下界可行流


    http://fastvj.rainng.com/contest/236779#problem/G

    Description:

      n 行 m 列

      给你行和 与 列和

      然后有Q个限制,表示特定单元格元素大小的范围,最后问你可行的矩阵值

    Solution:
      有源汇上下界最大流问题,初始源点 连 行和流量是该行对应得行和,然后列连初始汇点,容量为列的列和,详细的限制,对应于行列之间,因为我最后要输出一个矩阵,所以n * m每一条边都要链接最后,手动连一条 t s inf的边,变成无源汇有上下界可行流问题,然后拆边,把对应边的流量,放到数组里,输出就好啦

    Code:

      前面比较基础的Dinic,数据操作函数,加边操作

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #define inf (1 << 28)
    using namespace std;
    const int maxn = 25;
    const int maxm = 210;
    const int mn = 505;
    const int mm = 440020;
    struct node{
        int to,val,pre,lid;
    }e[mm];
    int id[mn],cnt=0;
    
    int cur[mn];
    int flor[mn];
    
    int upflow[mn];
    int lowf[maxm][maxn];
    int upf[maxm][maxn];
    int out[maxm][maxn];
    void init()
    {
        memset(id,-1,sizeof(id));
        memset(upflow,0,sizeof(upflow));
        cnt = 0;
    }
    void add(int from,int to,int val,int lid)
    {
        e[cnt].to = to;
        e[cnt].val = val;
        e[cnt].lid = lid;
        e[cnt].pre = id[from];
        id[from] = cnt++;
        swap(from,to);
        e[cnt].to = to;
        e[cnt].val = 0;
        e[cnt].lid = lid;
        e[cnt].pre = id[from];
        id[from] = cnt++;
    }
    void addflow(int from,int to,int low,int up,int lid)
    {
        upflow[from] -= low;
        upflow[to] += low;
        add(from,to,up-low,lid);
    }
    bool bfs(int s,int t)
    {
        memset(flor,0,sizeof(flor));
        flor[s] = 1;
        queue<int> q;
        while(q.size())q.pop();
    
        q.push(s);
        while(q.size())
        {
            int now = q.front();
            q.pop();
    
            for(int i = id[now];~i;i = e[i].pre)
            {
                int to = e[i].to;
                int val = e[i].val;
                if(val > 0 && flor[to] == 0)
                {
                    flor[to] = flor[now] + 1;
                    q.push(to);
                    if(to == t)
                        return true;
                }
            }
        }
        return false;
    }
    int dfs(int s,int t,int value)
    {
        if(s == t || value == 0)return value;
    
        int ret = value,a;
    
        for(int &i = cur[s];~i;i = e[i].pre)
        {
            int val = e[i].val;
            int to = e[i].to;
            if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,val))))
            {
                e[i].val -= a;
                e[i^1].val += a;
                ret -= a;
                if(ret == 0)break;
            }
        }
        if(ret == value)flor[s] = 0;
        return value - ret;
    }
    
    int Dinic(int s,int t)
    {
        int ret = 0;
        while(bfs(s,t))
        {
            memcpy(cur,id,sizeof(id));
            ret += dfs(s,t,inf);
        }
        return ret;
    }
    
    void addlimit(int i,int j,char op,int lim)
    {
        if(op == '=')
        {
            upf[i][j] = lowf[i][j] = lim;
        }
        else if(op == '>')
        {
            lowf[i][j] = max(lowf[i][j],lim+1);
        }
        else
        {
            upf[i][j] = min(upf[i][j],lim-1);
        }
    }
    

     然后根据输入一点点的加边,这是行和和列和对应的边

    scanf("%d%d",&n,&m);
            s = 0;
            t = n + m + 1;
            ss = t + 1;
            tt = ss + 1;
            int lsum;
            for(int i = 1;i <= n;++i)
            {
                scanf("%d",&lsum);
                addflow(s,i,lsum,lsum,0);
            }
            for(int i = 1;i <= m;++i)
            {
                scanf("%d",&lsum);
                addflow(n + i,t,lsum,lsum,0);
            }
            int limitnum;
    

     然后根据题目中给出的限制条件,填充上下界数组

    scanf("%d",&limitnum);
            for(int i = 1;i <= n;++i)
            {
                for(int j = 1;j <= m;++j)
                {
                    lowf[i][j] = 0;
                    upf[i][j] = inf;
                }
            }
            int row,col,lim;
            char op;
            for(int i = 1;i <= limitnum;++i)
            {
                scanf("%d %d %c %d",&row,&col,&op,&lim);
                if(row == 0 && col == 0)
                {
                    for(int i = 1;i <= n;++i)
                    {
                        for(int j = 1;j <= m;++j)
                        {
                            addlimit(i,j,op,lim);
                        }
                    }
                }
                else if(row == 0)
                {
                    for(int i = 1;i <= n;++i)
                    {
                        addlimit(i,col,op,lim);
                    }
                }
                else if(col == 0)
                {
                    for(int i = 1;i <= m;++i)
                    {
                        addlimit(row,i,op,lim);
                    }
                }
                else
                {
                    addlimit(row,col,op,lim);
    
                }
            }
    

     根据上下界数组,添加有上下界边

    int tot = 0;
            for(int i = 1;i <= n;++i)
            {
                for(int j = 1;j <= m;++j)
                {
                    addflow(i,n+j,lowf[i][j],upf[i][j],++tot);
                }
            }
    

     加边完成后,转化为无源汇有上下界可行流 ———— 循环流

    add(t,s,inf,0);
            int sum = 0;
            for(int i = s;i <= t;++i)
            {
                if(upflow[i] < 0)
                {
                    add(i,tt,-upflow[i],0);
                }
                else
                {
                    sum += upflow[i];
                    add(ss,i,upflow[i],0);
                }
            }
    

     跑DIinc,如果存在可行流的话

    就输出叭~~

    for(int now = n+1;now <= n + m;++now)
                {
                    for(int i = id[now];~i;i = e[i].pre)
                    {
                        int to = e[i].to;
                        int lid = e[i].lid;
                        if(lid == 0 || i % 2 == 0)continue;
                        out[to][now-n] = lowf[to][now-n] + e[i].val;
                    }
                }
                for(int i = 1;i <= n;++i)
                {
                    for(int j = 1;j <= m;++j)
                    {
                        if(j == 1)
                            printf("%d",out[i][j]);
                        else
                            printf(" %d",out[i][j]);
                    }
                    printf("
    ");
                }
    

     完整代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #define inf (1 << 28)
    using namespace std;
    const int maxn = 25;
    const int maxm = 210;
    const int mn = 505;
    const int mm = 440020;
    struct node{
        int to,val,pre,lid;
    }e[mm];
    int id[mn],cnt=0;
    
    int cur[mn];
    int flor[mn];
    
    int upflow[mn];
    int lowf[maxm][maxn];
    int upf[maxm][maxn];
    int out[maxm][maxn];
    void init()
    {
        memset(id,-1,sizeof(id));
        memset(upflow,0,sizeof(upflow));
        cnt = 0;
    }
    void add(int from,int to,int val,int lid)
    {
        e[cnt].to = to;
        e[cnt].val = val;
        e[cnt].lid = lid;
        e[cnt].pre = id[from];
        id[from] = cnt++;
        swap(from,to);
        e[cnt].to = to;
        e[cnt].val = 0;
        e[cnt].lid = lid;
        e[cnt].pre = id[from];
        id[from] = cnt++;
    }
    void addflow(int from,int to,int low,int up,int lid)
    {
        upflow[from] -= low;
        upflow[to] += low;
        add(from,to,up-low,lid);
    }
    bool bfs(int s,int t)
    {
        memset(flor,0,sizeof(flor));
        flor[s] = 1;
        queue<int> q;
        while(q.size())q.pop();
    
        q.push(s);
        while(q.size())
        {
            int now = q.front();
            q.pop();
    
            for(int i = id[now];~i;i = e[i].pre)
            {
                int to = e[i].to;
                int val = e[i].val;
                if(val > 0 && flor[to] == 0)
                {
                    flor[to] = flor[now] + 1;
                    q.push(to);
                    if(to == t)
                        return true;
                }
            }
        }
        return false;
    }
    int dfs(int s,int t,int value)
    {
        if(s == t || value == 0)return value;
    
        int ret = value,a;
    
        for(int &i = cur[s];~i;i = e[i].pre)
        {
            int val = e[i].val;
            int to = e[i].to;
            if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,val))))
            {
                e[i].val -= a;
                e[i^1].val += a;
                ret -= a;
                if(ret == 0)break;
            }
        }
        if(ret == value)flor[s] = 0;
        return value - ret;
    }
    
    int Dinic(int s,int t)
    {
        int ret = 0;
        while(bfs(s,t))
        {
            memcpy(cur,id,sizeof(id));
            ret += dfs(s,t,inf);
        }
        return ret;
    }
    
    void addlimit(int i,int j,char op,int lim)
    {
        if(op == '=')
        {
            upf[i][j] = lowf[i][j] = lim;
        }
        else if(op == '>')
        {
            lowf[i][j] = max(lowf[i][j],lim+1);
        }
        else
        {
            upf[i][j] = min(upf[i][j],lim-1);
        }
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        int n,m,s,t,ss,tt;
        while(T--)
        {
            init();
            scanf("%d%d",&n,&m);
            s = 0;
            t = n + m + 1;
            ss = t + 1;
            tt = ss + 1;
            int lsum;
            for(int i = 1;i <= n;++i)
            {
                scanf("%d",&lsum);
                addflow(s,i,lsum,lsum,0);
            }
            for(int i = 1;i <= m;++i)
            {
                scanf("%d",&lsum);
                addflow(n + i,t,lsum,lsum,0);
            }
            int limitnum;
            scanf("%d",&limitnum);
            for(int i = 1;i <= n;++i)
            {
                for(int j = 1;j <= m;++j)
                {
                    lowf[i][j] = 0;
                    upf[i][j] = inf;
                }
            }
            int row,col,lim;
            char op;
            for(int i = 1;i <= limitnum;++i)
            {
                scanf("%d %d %c %d",&row,&col,&op,&lim);
                if(row == 0 && col == 0)
                {
                    for(int i = 1;i <= n;++i)
                    {
                        for(int j = 1;j <= m;++j)
                        {
                            addlimit(i,j,op,lim);
                        }
                    }
                }
                else if(row == 0)
                {
                    for(int i = 1;i <= n;++i)
                    {
                        addlimit(i,col,op,lim);
                    }
                }
                else if(col == 0)
                {
                    for(int i = 1;i <= m;++i)
                    {
                        addlimit(row,i,op,lim);
                    }
                }
                else
                {
                    addlimit(row,col,op,lim);
    
                }
            }
            int tot = 0;
            for(int i = 1;i <= n;++i)
            {
                for(int j = 1;j <= m;++j)
                {
                    addflow(i,n+j,lowf[i][j],upf[i][j],++tot);
                }
            }
            add(t,s,inf,0);
            int sum = 0;
            for(int i = s;i <= t;++i)
            {
                if(upflow[i] < 0)
                {
                    add(i,tt,-upflow[i],0);
                }
                else
                {
                    sum += upflow[i];
                    add(ss,i,upflow[i],0);
                }
            }
            if(Dinic(ss,tt) == sum)
            {
                for(int now = n+1;now <= n + m;++now)
                {
                    for(int i = id[now];~i;i = e[i].pre)
                    {
                        int to = e[i].to;
                        int lid = e[i].lid;
                        if(lid == 0 || i % 2 == 0)continue;
                        out[to][now-n] = lowf[to][now-n] + e[i].val;
                    }
                }
                for(int i = 1;i <= n;++i)
                {
                    for(int j = 1;j <= m;++j)
                    {
                        if(j == 1)
                            printf("%d",out[i][j]);
                        else
                            printf(" %d",out[i][j]);
                    }
                    printf("
    ");
                }
            }
            else
            {
                printf("IMPOSSIBLE
    ");
            }
            if(T)printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    android Fragment和FragmentActivity
    android 生成xml文件
    android:在ViewPager中使用Button
    android延迟执行
    android.os.NetworkOnMainThreadException 异常
    导入android工程没有R文件的解决办法
    20个常用的Java程序块
    Java中的==、equals、hasCode方法
    《head first java 》读书笔记
    【写给自己】2014-03-13
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9740863.html
Copyright © 2020-2023  润新知