zoukankan      html  css  js  c++  java
  • P4013 数字梯形问题 【网络流24题】

    题目描述

    给定一个由 nn 行数字组成的数字梯形如下图所示。

    梯形的第一行有 mm 个数字。从梯形的顶部的 mm 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。

    分别遵守以下规则:

    1. 从梯形的顶至底的 mm 条路径互不相交;

    2. 从梯形的顶至底的 mm 条路径仅在数字结点处相交;

    3. 从梯形的顶至底的 mm 条路径允许在数字结点相交或边相交。

    输入格式

    第 11 行中有 22 个正整数 mm 和 nn,分别表示数字梯形的第一行有 mm 个数字,共有 nn 行。接下来的 nn 行是数字梯形中各行的数字。

    第 11 行有 mm 个数字,第 22 行有 m+1m+1 个数字,以此类推。

    输出格式

    将按照规则 11,规则 22,和规则 33 计算出的最大数字总和并输出,每行一个最大总和。

    输入输出样例

    输入 #1
    2 5
    2 3
    3 4 5
    9 10 9 1
    1 1 10 1 1
    1 1 10 12 1 1
    输出 #1
    66
    75
    77

    说明/提示

    1leq m,n leq 201m,n20

    思路

      路径问题,关乎点权

      以及三种限制条件

      很容易想到这就是一个最大费用最大流问题

      已经知道了这是一个最大费用最大流问题

      就可以着手建图了

      因为我们要求一个点权和的最大值

      而网络流是无法解决点权的问题的

      显然可以把点权转化成边权来做

      也就是把一个点拆开成 X,Y 两个点

      这个点的点权就是X、Y之间的边权

      首先这道题有三个子任务点

      (一)、路径互不相交

      显然如果要路径互不相交,也就是既没有公共点,也没有公共边

      所以,要建出这种限制相当容易,只需要让每个点Xi、Yi之间的流量为1.

      且每个点和它下方相连的点的边的流量也应该为1

      这样就可以成功限制每个点每条边都只能用一次这个条件

      (二)、只能在点处相交

      换句话说就是一个点能用多次

      所以其他建图条件可以不变,把对点Xi和Yi之间的限制解除即可

      (三)、只能在点和边相交

      此时就已经完全没有限制条件了

      除了超级源向第一行连边依然是1以外

      其他所有的边的流量都可以置为无穷

      具体详见代码

    CODE

      1 #include <bits/stdc++.h>
      2 #define dbg(x) cout << #x << "=" << x << endl
      3 #define eps 1e-8
      4 #define pi acos(-1.0)
      5 
      6 using namespace std;
      7 typedef long long LL;
      8 const int maxn = 1e5 +7;
      9 const int inf  = 0x3f3f3f3f;
     10 
     11 int n, m, s, t;
     12 int head[maxn],pre[maxn],inq[maxn],dis[maxn];
     13 int cnt = 1;
     14 int mincost = 0, maxflow = 0;
     15 struct edge {
     16     int u,to,nxt,w,c;
     17 }e[maxn << 1];
     18 
     19 template<class T>inline void read(T &res)
     20 {
     21     char c;T flag=1;
     22     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     23     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     24 }
     25 
     26 inline void BuildGraph(int u, int v, int w, int cost)
     27 {
     28     e[++cnt] = (edge){u, v, head[u], w,  cost}, head[u] = cnt;
     29     e[++cnt] = (edge){v, u, head[v], 0, -cost}, head[v] = cnt;///反向边
     30 }
     31 
     32 queue<int> q;
     33 
     34 inline void init() {
     35     memset(head, 0, sizeof(head));
     36     memset(pre, 0, sizeof(pre));
     37     memset(inq, 0, sizeof(inq));
     38     memset(dis, 0, sizeof(dis));
     39     memset(e, 0, sizeof(e));
     40     while(!q.empty()) {
     41         q.pop();
     42     }
     43     mincost = maxflow = 0;
     44     cnt = 1;
     45 }
     46 
     47 bool SPFA(int x)
     48 {
     49     memset(inq, 0, sizeof(inq));
     50     for(int i = s; i <= t; i++) {
     51         dis[i] = inf;
     52     }
     53     q.push(x);
     54     dis[x] = 0;
     55     inq[x] = 1;
     56     while(!q.empty()) {
     57         int u = q.front();
     58         q.pop();
     59         inq[u] = 0;
     60         for(int i = head[u]; i; i = e[i].nxt) {
     61             int v = e[i].to, w = e[i].c;
     62             if(e[i].w > 0) {
     63                 if(dis[u] + w < dis[v]) {
     64                     dis[v] = dis[u] + w;
     65                     pre[v] = i;
     66                     if(!inq[v]) {
     67                         q.push(v);
     68                         inq[v] = 1;
     69                     }
     70                 }
     71             }
     72         }
     73     }
     74     if(dis[t] == inf)
     75         return 0;
     76     return 1;
     77 }
     78 
     79 void MCMF()
     80 {
     81     while(SPFA(s)) {
     82         int temp = inf;
     83         for(int i = pre[t]; i; i = pre[e[i].u]) {
     84             temp = min(temp, e[i].w);
     85         }
     86         for(int i = pre[t]; i; i = pre[e[i].u]) {
     87             e[i].w   -= temp;
     88             e[i^1].w += temp;
     89             mincost += e[i].c * temp;
     90             //printf("maxflow:%d mincost:%d
    ",maxflow, mincost);
     91         }
     92         maxflow += temp;
     93     }
     94 }
     95 
     96 int a[1007][1007];
     97 int Depth_Size = 0;
     98 
     99 inline int id1(int a, int b) {
    100     return (a-1) * Depth_Size + b;
    101 }
    102 
    103 inline int id2(int a, int b) {
    104     return n * Depth_Size + (a - 1) * Depth_Size + b;
    105 }
    106 
    107 void task1() {
    108     //! 3 5 9 10 12 = 39
    109     //! 2 4 10 1 10 = 27
    110     init();
    111     s = 0, t = n * Depth_Size * 3 + 1;
    112     int temp = m + 1;
    113     for ( int i = 1; i <= m; ++i ) {
    114         BuildGraph(s, id1(1, i), 1, 0);
    115         BuildGraph(id1(1, i), id2(1, i), 1, -a[1][i]);
    116         BuildGraph(id2(1, i), id1(2, i), 1, 0);
    117         BuildGraph(id2(1, i), id1(2, i + 1), 1, 0);
    118         //printf("u:%d v:%d cost:%d
    ",id1(1, i), id2(1, i), -a[1][i]);
    119     }
    120     for ( int i = 2; i <= n - 1; ++i ) {
    121         for ( int j = 1; j <= temp; ++j ) {
    122             BuildGraph(id1(i, j), id2(i, j), 1, -a[i][j]);
    123             BuildGraph(id2(i, j), id1(i + 1, j), 1, 0);
    124             BuildGraph(id2(i, j), id1(i + 1, j + 1), 1, 0);
    125             //printf("u:%d v:%d cost:%d
    ",id1(i, j), id2(i, j), -a[i][j]);
    126         }
    127         ++temp;
    128     }
    129     for ( int i = 1; i <= temp; ++i ) {
    130         BuildGraph(id1(n, i), id2(n, i), 1, -a[n][i]);
    131         BuildGraph(id2(n, i), t, 1, 0);
    132         //printf("u:%d v:%d cost:%d
    ",id1(n, i), id2(n, i), -a[n][i]);
    133     }
    134     //dbg(t);
    135     MCMF();
    136     //dbg(maxflow);
    137     cout << -mincost << endl;
    138 }
    139 
    140 void task2() {
    141     init();
    142     s = 0, t = n * Depth_Size * 3 + 1;
    143     int temp = m + 1;
    144     for ( int i = 1; i <= m; ++i ) {
    145         BuildGraph(s, id1(1, i), 1, 0);
    146         BuildGraph(id1(1, i), id2(1, i), inf, -a[1][i]);
    147         BuildGraph(id2(1, i), id1(2, i), 1, 0);
    148         BuildGraph(id2(1, i), id1(2, i + 1), 1, 0);
    149         //printf("u:%d v:%d cost:%d
    ",id1(1, i), id2(1, i), -a[1][i]);
    150     }
    151     for ( int i = 2; i <= n - 1; ++i ) {
    152         for ( int j = 1; j <= temp; ++j ) {
    153             BuildGraph(id1(i, j), id2(i, j), inf, -a[i][j]);
    154             BuildGraph(id2(i, j), id1(i + 1, j), 1, 0);
    155             BuildGraph(id2(i, j), id1(i + 1, j + 1), 1, 0);
    156             //printf("u:%d v:%d cost:%d
    ",id1(i, j), id2(i, j), -a[i][j]);
    157         }
    158         ++temp;
    159     }
    160     for ( int i = 1; i <= temp; ++i ) {
    161         BuildGraph(id1(n, i), id2(n, i), inf, -a[n][i]);
    162         BuildGraph(id2(n, i), t, inf, 0);
    163         //printf("u:%d v:%d cost:%d
    ",id1(n, i), id2(n, i), -a[n][i]);
    164     }
    165     //dbg(t);
    166     MCMF();
    167     //dbg(maxflow);
    168     cout << -mincost << endl;
    169 }
    170 
    171 void task3() {
    172     init();
    173     s = 0, t = n * Depth_Size * 3 + 1;
    174     int temp = m + 1;
    175     for ( int i = 1; i <= m; ++i ) {
    176         BuildGraph(s, id1(1, i), 1, 0);
    177         BuildGraph(id1(1, i), id2(1, i), inf, -a[1][i]);
    178         BuildGraph(id2(1, i), id1(2, i), inf, 0);
    179         BuildGraph(id2(1, i), id1(2, i + 1), inf, 0);
    180         //printf("u:%d v:%d cost:%d
    ",id1(1, i), id2(1, i), -a[1][i]);
    181     }
    182     for ( int i = 2; i <= n - 1; ++i ) {
    183         for ( int j = 1; j <= temp; ++j ) {
    184             BuildGraph(id1(i, j), id2(i, j), inf, -a[i][j]);
    185             BuildGraph(id2(i, j), id1(i + 1, j), inf, 0);
    186             BuildGraph(id2(i, j), id1(i + 1, j + 1), inf, 0);
    187             //printf("u:%d v:%d cost:%d
    ",id1(i, j), id2(i, j), -a[i][j]);
    188         }
    189         ++temp;
    190     }
    191     for ( int i = 1; i <= temp; ++i ) {
    192         BuildGraph(id1(n, i), id2(n, i), inf, -a[n][i]);
    193         BuildGraph(id2(n, i), t, inf, 0);
    194         //printf("u:%d v:%d cost:%d
    ",id1(n, i), id2(n, i), -a[n][i]);
    195     }
    196     //dbg(t);
    197     MCMF();
    198     //dbg(maxflow);
    199     cout << -mincost << endl;
    200 }
    201 
    202 int main()  
    203 {
    204     //freopen("data.txt", "r", stdin);
    205     read(m); read(n);
    206     Depth_Size = m;
    207     for ( int i = 1; i <= n; ++i ) {
    208         for ( int j = 1; j <= Depth_Size; ++j ) {
    209             read(a[i][j]);
    210             //printf("a[%d][%d]:%d%c",i, j, a[i][j], j == Depth_Size ? '
    ' : ' ');
    211         }
    212         ++Depth_Size;
    213     }
    214     task1();
    215     task2();
    216     task3();
    217     return 0;
    218 }
    View Code

     

    #include <bits/stdc++.h>
    #define dbg(x) cout << #x << "=" << x << endl
    #define eps 1e-8
    #define pi acos(-1.0)

    using namespace std;
    typedef long long LL;
    const int maxn = 1e5 +7;
    const int inf  = 0x3f3f3f3f;

    int n, m, s, t;
    int head[maxn],pre[maxn],inq[maxn],dis[maxn];
    int cnt = 1;
    int mincost = 0, maxflow = 0;
    struct edge {
        int u,to,nxt,w,c;
    }e[maxn << 1];

    template<class T>inline void read(T &res)
    {
        char c;T flag=1;
        while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
        while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }

    inline void BuildGraph(int uint vint wint cost)
    {
        e[++cnt] = (edge){u, v, head[u], w,  cost}, head[u] = cnt;
        e[++cnt] = (edge){v, u, head[v], 0-cost}, head[v] = cnt;///反向边
    }

    queue<int> q;

    inline void init() {
        memset(head, 0sizeof(head));
        memset(pre, 0sizeof(pre));
        memset(inq, 0sizeof(inq));
        memset(dis, 0sizeof(dis));
        memset(e, 0sizeof(e));
        while(!q.empty()) {
            q.pop();
        }
        mincost = maxflow = 0;
        cnt = 1;
    }

    bool SPFA(int x)
    {
        memset(inq, 0sizeof(inq));
        for(int i = s; i <= t; i++) {
            dis[i] = inf;
        }
        q.push(x);
        dis[x] = 0;
        inq[x] = 1;
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            inq[u] = 0;
            for(int i = head[u]; i; i = e[i].nxt) {
                int v = e[i].to, w = e[i].c;
                if(e[i].w > 0) {
                    if(dis[u] + w < dis[v]) {
                        dis[v] = dis[u] + w;
                        pre[v] = i;
                        if(!inq[v]) {
                            q.push(v);
                            inq[v] = 1;
                        }
                    }
                }
            }
        }
        if(dis[t] == inf)
            return 0;
        return 1;
    }

    void MCMF()
    {
        while(SPFA(s)) {
            int temp = inf;
            for(int i = pre[t]; i; i = pre[e[i].u]) {
                temp = min(temp, e[i].w);
            }
            for(int i = pre[t]; i; i = pre[e[i].u]) {
                e[i].w   -= temp;
                e[i^1].w += temp;
                mincost += e[i].c * temp;
                //printf("maxflow:%d mincost:%d ",maxflow, mincost);
            }
            maxflow += temp;
        }
    }

    int a[1007][1007];
    int Depth_Size = 0;

    inline int id1(int aint b) {
        return (a-1* Depth_Size + b;
    }

    inline int id2(int aint b) {
        return n * Depth_Size + (a - 1* Depth_Size + b;
    }

    void task1() {
        //! 3 5 9 10 12 = 39
        //! 2 4 10 1 10 = 27
        init();
        s = 0, t = n * Depth_Size * 3 + 1;
        int temp = m + 1;
        for ( int i = 1; i <= m; ++i ) {
            BuildGraph(s, id1(1, i), 10);
            BuildGraph(id1(1, i), id2(1, i), 1-a[1][i]);
            BuildGraph(id2(1, i), id1(2, i), 10);
            BuildGraph(id2(1, i), id1(2, i + 1), 10);
            //printf("u:%d v:%d cost:%d ",id1(1, i), id2(1, i), -a[1][i]);
        }
        for ( int i = 2; i <= n - 1++i ) {
            for ( int j = 1; j <= temp; ++j ) {
                BuildGraph(id1(i, j), id2(i, j), 1-a[i][j]);
                BuildGraph(id2(i, j), id1(i + 1, j), 10);
                BuildGraph(id2(i, j), id1(i + 1, j + 1), 10);
                //printf("u:%d v:%d cost:%d ",id1(i, j), id2(i, j), -a[i][j]);
            }
            ++temp;
        }
        for ( int i = 1; i <= temp; ++i ) {
            BuildGraph(id1(n, i), id2(n, i), 1-a[n][i]);
            BuildGraph(id2(n, i), t, 10);
            //printf("u:%d v:%d cost:%d ",id1(n, i), id2(n, i), -a[n][i]);
        }
        //dbg(t);
        MCMF();
        //dbg(maxflow);
        cout << -mincost << endl;
    }

    void task2() {
        init();
        s = 0, t = n * Depth_Size * 3 + 1;
        int temp = m + 1;
        for ( int i = 1; i <= m; ++i ) {
            BuildGraph(s, id1(1, i), 10);
            BuildGraph(id1(1, i), id2(1, i), inf, -a[1][i]);
            BuildGraph(id2(1, i), id1(2, i), 10);
            BuildGraph(id2(1, i), id1(2, i + 1), 10);
            //printf("u:%d v:%d cost:%d ",id1(1, i), id2(1, i), -a[1][i]);
        }
        for ( int i = 2; i <= n - 1++i ) {
            for ( int j = 1; j <= temp; ++j ) {
                BuildGraph(id1(i, j), id2(i, j), inf, -a[i][j]);
                BuildGraph(id2(i, j), id1(i + 1, j), 10);
                BuildGraph(id2(i, j), id1(i + 1, j + 1), 10);
                //printf("u:%d v:%d cost:%d ",id1(i, j), id2(i, j), -a[i][j]);
            }
            ++temp;
        }
        for ( int i = 1; i <= temp; ++i ) {
            BuildGraph(id1(n, i), id2(n, i), inf, -a[n][i]);
            BuildGraph(id2(n, i), t, inf, 0);
            //printf("u:%d v:%d cost:%d ",id1(n, i), id2(n, i), -a[n][i]);
        }
        //dbg(t);
        MCMF();
        //dbg(maxflow);
        cout << -mincost << endl;
    }

    void task3() {
        init();
        s = 0, t = n * Depth_Size * 3 + 1;
        int temp = m + 1;
        for ( int i = 1; i <= m; ++i ) {
            BuildGraph(s, id1(1, i), 10);
            BuildGraph(id1(1, i), id2(1, i), inf, -a[1][i]);
            BuildGraph(id2(1, i), id1(2, i), inf, 0);
            BuildGraph(id2(1, i), id1(2, i + 1), inf, 0);
            //printf("u:%d v:%d cost:%d ",id1(1, i), id2(1, i), -a[1][i]);
        }
        for ( int i = 2; i <= n - 1++i ) {
            for ( int j = 1; j <= temp; ++j ) {
                BuildGraph(id1(i, j), id2(i, j), inf, -a[i][j]);
                BuildGraph(id2(i, j), id1(i + 1, j), inf, 0);
                BuildGraph(id2(i, j), id1(i + 1, j + 1), inf, 0);
                //printf("u:%d v:%d cost:%d ",id1(i, j), id2(i, j), -a[i][j]);
            }
            ++temp;
        }
        for ( int i = 1; i <= temp; ++i ) {
            BuildGraph(id1(n, i), id2(n, i), inf, -a[n][i]);
            BuildGraph(id2(n, i), t, inf, 0);
            //printf("u:%d v:%d cost:%d ",id1(n, i), id2(n, i), -a[n][i]);
        }
        //dbg(t);
        MCMF();
        //dbg(maxflow);
        cout << -mincost << endl;
    }

    int main()  
    {
        //freopen("data.txt", "r", stdin);
        read(m); read(n);
        Depth_Size = m;
        for ( int i = 1; i <= n; ++i ) {
            for ( int j = 1; j <= Depth_Size; ++j ) {
                read(a[i][j]);
                //printf("a[%d][%d]:%d%c",i, j, a[i][j], j == Depth_Size ? ' ' : ' ');
            }
            ++Depth_Size;
        }
        task1();
        task2();
        task3();
        return 0;
    }
  • 相关阅读:
    第194场周赛
    刷leetcode的心得
    91. Decode Ways
    23. Merge k Sorted Lists
    19. Remove Nth Node From End of List
    21. Merge Two Sorted Lists
    222. Count Complete Tree Nodes
    958. Check Completeness of a Binary Tree
    课程学习总结报告
    结合中断上下文切换和进程上下文切换分析Linux内核一般执行过程
  • 原文地址:https://www.cnblogs.com/orangeko/p/12824530.html
Copyright © 2011-2022 走看看