• 数字梯形问题(费用流,最大权不相交路径,网络流24题)


    题意

    思路

    • 第一问

    (m)条路径中,每个点只能使用(1)次,每条边也只能使用(1)次,获益为经过点的点权和。

    这里的费用不是边的费用,而是点的费用,因此可以采用拆点的技巧,即拆成一个入点和一个出点,入点与出点连边,容量是(1)(因为每个点只能使用一次),费用是点权。

    设立虚拟源点(S),与第一行的(m)个数字的入点连边,容量是(1)(因为每个点只能使用一次),费用是(0)(费用只能出现在入点指向出点的边上)。

    设立虚拟汇点(T),最后一行的数字与(T)的出点连边,容量是(1),费用是(0)

    每个点的出点与之斜下方两点的入点连边,容量是(1),费用是(0)

    跑最大费用流即可。

    • 第二问

    每个点的使用次数不限,但是值得注意的是第一行的点只能使用(1)次,原因是一开始每个点只使用了一次,并且中间过程中不会再到达第一行的数字。每条边还是只能使用(1)次。

    因此,与第一问相比,需要修改的地方是,入点连向出点的边,容量改成(infty)。最后一行数字的出点,指向(T)的边的容量改成(infty)

    • 第三问

    每个点的使用次数不限,第一行的点只能使用(1)次,每条边也可以使用无限次。

    因此,与第二问相比,需要修改的地方是,每个点的出点指向斜下方两点的入点的容量改成(infty)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int N = 1200, M = 4000, inf = 1e8;
    
    int n, m, S, T;
    int h[N], e[M], ne[M], f[M], w[M], idx;
    int pre[N], d[N], incf[N];
    bool st[N];
    int cost[25][25], id[25][25];
    
    void add(int a, int b, int c, int d)
    {
        e[idx] = b, f[idx] = c, w[idx] = d, ne[idx] = h[a], h[a] = idx ++;
        e[idx] = a, f[idx] = 0, w[idx] = -d, ne[idx] = h[b], h[b] = idx ++;
    }
    
    bool spfa()
    {
        memset(d, 0x3f, sizeof(d));
        memset(incf, 0, sizeof(incf));
        queue<int> que;
        que.push(S);
        d[S] = 0, incf[S] = inf;
        st[S] = true;
        while(que.size()) {
            int t = que.front();
            que.pop();
            st[t] = false;
            for(int i = h[t]; ~i; i = ne[i]) {
                int ver = e[i];
                if(d[ver] > d[t] + w[i] && f[i]) {
                    d[ver] = d[t] + w[i];
                    pre[ver] = i;
                    incf[ver] = min(incf[t], f[i]);
                    if(!st[ver]) {
                        que.push(ver);
                        st[ver] = false;
                    }
                }
            }
        }
        return incf[T] > 0;
    }
    
    int EK()
    {
        int cost = 0;
        while(spfa()) {
            int t = incf[T];
            cost += t * d[T];
            for(int i = T; i != S; i = e[pre[i] ^ 1]) {
                f[pre[i]] -= t;
                f[pre[i] ^ 1] += t;
            }
        }
        return cost;
    }
    
    int main()
    {
        scanf("%d%d", &m, &n);
        int cnt = 0;
        S = ++ cnt;
        T = ++ cnt;
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m + i - 1; j ++) {
                scanf("%d", &cost[i][j]);
                id[i][j] = ++ cnt;
            }
        }
        memset(h, -1, sizeof(h));
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m + i - 1; j ++) {
                int in = id[i][j] * 2, out = in + 1;
                add(in, out, 1, -cost[i][j]);
                if(i == 1) add(S, in, 1, 0);
                if(i == n) add(out, T, 1, 0);
                if(i < n) {
                    add(out, id[i + 1][j] * 2, 1, 0);
                    add(out, id[i + 1][j + 1] * 2, 1, 0);
                }
            }
        }
        printf("%d
    ", -EK());
        memset(h, -1, sizeof(h));
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m + i - 1; j ++) {
                int in = id[i][j] * 2, out = in + 1;
                add(in, out, inf, -cost[i][j]);
                if(i == 1) add(S, in, 1, 0);
                if(i == n) add(out, T, inf, 0);
                if(i < n) {
                    add(out, id[i + 1][j] * 2, 1, 0);
                    add(out, id[i + 1][j + 1] * 2, 1, 0);
                }
            }
        }
        printf("%d
    ", -EK());
        memset(h, -1, sizeof(h));
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m + i - 1; j ++) {
                int in = id[i][j] * 2, out = in + 1;
                add(in, out, inf, -cost[i][j]);
                if(i == 1) add(S, in, 1, 0);
                if(i == n) add(out, T, inf, 0);
                if(i < n) {
                    add(out, id[i + 1][j] * 2, inf, 0);
                    add(out, id[i + 1][j + 1] * 2, inf, 0);
                }
            }
        }
        printf("%d
    ", -EK());
        return 0;
    }
    
  • 相关阅读:
    高并发处理(一)页面静态化
    高并发处理(二)图片服务器分离
    五百强企业某部门视频面试题汇总
    access和sqlyog的使用
    条件查询
    primary select |||| case primary select
    win10 + ubuntu16 双系统安装
    ubuntu16 下安装python3.6 和Anaconda3
    import nltk nltk.download('reuters') [nltk_data] Error loading reuters: <urlopen error [Errno 11004] [nltk_data] getaddrinfo failed>
    共现矩阵
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14413304.html
Copyright © 2020-2023  润新知