【上下界网络流 费用流】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
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