【上下界网络流 费用流】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\n",ans);
70     return 0;
71 }

 

 

END

posted @ 2019-03-01 21:26  AntiQuality  阅读(137)  评论(0编辑  收藏  举报