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