• 【上下界网络流 费用流】bzoj2055: 80人环游世界


    EK费用流居然写错了……

    Description

        想必大家都看过成龙大哥的《80天环游世界》,里面的紧张刺激的打斗场面一定给你留下了深刻的印象。现在就有这么
        一个80人的团伙,也想来一次环游世界。
        他们打算兵分多路,游遍每一个国家。
        因为他们主要分布在东方,所以他们只朝西方进军。设从东方到西方的每一个国家的编号依次为1...N。假若第i个人的游历路线为P1、P2......Pk(0≤k≤N),则P1<P2<......<Pk。
        众所周知,中国相当美丽,这样在环游世界时就有很多人经过中国。我们用一个正整数Vi来描述一个国家的吸引程度,Vi值越大表示该国家越有吸引力,同时也表示有且仅
    有Vi个人会经过那一个国家。
        为了节省时间,他们打算通过坐飞机来完成环游世界的任务。同时为了省钱,他们希望总的机票费最小。
        明天就要出发了,可是有些人临阵脱逃,最终只剩下了M个人去环游世界。他们想知道最少的总费用,你能告诉他们吗?

    Input

    第一行两个正整数N,M。
    第二行有N个不大于M正整数,分别表示V1,V2......VN。
    接下来有N-1行。第i行有N-i个整数,该行的第j个数表示从第i个国家到第i+j个国家的机票费(如果该值等于-1则表示这两个国家间没有通航)。

    Output

    在第一行输出最少的总费用。

    Sample Input

    6 3
    2 1 3 1 2 1
    2 6 8 5 0
    8 2 4 1
    6 1 0
    4 -1
    4

    Sample Output

    27

    HINT

    1<= N < =100 1<= M <= 79


    题目分析

    这就是一个无源汇最小费用最大流的模型,关于M个人的限制则是把(TT,SS)的边流量设为M

    掌握得还是不够熟练啊

     1 #include<bits/stdc++.h>
     2 const int maxn = 503;
     3 const int maxm = 200035;
     4 const int INF = 2e9;
     5 
     6 struct Edge
     7 {
     8     int u,v,f,c,cst;
     9     Edge(int a=0, int b=0, int c=0, int d=0, int e=0):u(a),v(b),f(c),c(d),cst(e) {}
    10 }edges[maxm];
    11 int n,m,S,T,SS,TT,ans;
    12 int edgeTot,head[maxn],nxt[maxm],bck[maxm],cst[maxn],flw[maxn];
    13 bool inq[maxn<<2];
    14 
    15 void addedge(int u, int v, int c, int cst)
    16 {
    17     edges[edgeTot] = Edge(u, v, 0, c,  cst), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot;
    18     edges[edgeTot] = Edge(v, u, 0, 0, -cst), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot;
    19 }
    20 void maxFlow()
    21 {
    22     for (;;)
    23     {
    24         std::queue<int> q;
    25         memset(flw, 0, sizeof flw);
    26         memset(bck, 0, sizeof bck);
    27         memset(cst, 0x3f3f3f3f, sizeof cst);
    28         q.push(S), flw[S] = INF, cst[S] = 0;
    29         for (int tmp; q.size(); )
    30         {
    31             tmp = q.front(), q.pop(), inq[tmp] = 0;
    32             for (int i=head[tmp]; i!=-1; i=nxt[i])
    33             {
    34                 int v = edges[i].v;
    35                 if (cst[tmp]+edges[i].cst < cst[v]&&edges[i].f < edges[i].c){
    36                     cst[v] = cst[tmp]+edges[i].cst, bck[v] = i;
    37                     flw[v] = std::min(flw[tmp], edges[i].c-edges[i].f);
    38                     if (!inq[v]) q.push(v), inq[v] = 1;
    39                 }
    40             }
    41         }
    42         if (!flw[T]) break;
    43         for (int i=T; i!=S; i=edges[bck[i]].u)
    44             edges[bck[i]].f += flw[T], edges[bck[i]^1].f -= flw[T];
    45         ans += flw[T]*cst[T];
    46     }
    47 }
    48 int main()
    49 {
    50     memset(head, -1, sizeof head);
    51     scanf("%d%d",&n,&m);
    52     S = n+n+1, T = S+1, SS = T+1, TT = SS+1;
    53     for (int i=1,v; i<=n; i++)
    54     {
    55         scanf("%d",&v);
    56         addedge(S, i+n, v, 0);
    57         addedge(i, T, v, 0);
    58         addedge(SS, i, INF, 0);
    59         addedge(i+n, TT, INF, 0);
    60     }
    61     addedge(TT, SS, m, 0);
    62     for (int i=1; i<=n; i++)
    63         for (int j=1,x; j<=n-i; j++)
    64         {
    65             scanf("%d",&x);
    66             if (x!=-1) addedge(i+n, i+j, INF, x);
    67         }
    68     maxFlow();
    69     printf("%d
    ",ans);
    70     return 0;
    71 }

    END

  • 相关阅读:
    因数最多的数
    剪枝策略
    计蒜客 引爆炸弹(DFS、并查集)
    计蒜客 方程的解数(DFS)
    计蒜客 数独(DFS)
    计蒜客 王子救公主(DFS)
    kuangbin专题 专题九 连通图 POJ 3694 Network
    2019 ICPC Asia Nanjing Regional K. Triangle
    HDU 1875 畅通工程再续
    还是畅通工程 HDU
  • 原文地址:https://www.cnblogs.com/antiquality/p/10458859.html
Copyright © 2020-2023  润新知