2055: 80人环游世界

来源:互联网 发布:网络红猫包子脸猫 编辑:程序博客网 时间:2024/04/28 23:25

2055: 80人环游世界

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 366  Solved: 232
[Submit][Status][Discuss]

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

Source

[Submit][Status][Discuss]



转换模型,,等价于求有上下界的最小费用可行流

每个国家拆成两个点Ai,Bi,中间连上下界都为Vi的边

假设一个源点s,城市0,s向0连一条容量为m的边,0向所有城市的Ai连容量为INF的边

所有城市的Bi向汇点t连容量为INF的边,城市间的飞机就有Bi向Aj连边,容量INF,有费用

只要再连(t,s,INF)这条边就能构成循环流了,按照构建循环流的方法,跑一遍最小费用最大流就是答案了

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<algorithm>#include<cmath>using namespace std;const int maxn = 255;const int maxm = 4E5 + 40;const int INF = ~0U>>1;struct E{int to,cap,flow,cost; E(){}E(int to,int cap,int flow,int cost):to(to),cap(cap),flow(flow),cost(cost){}}edgs[maxm];int n,m,s,t,S,T,cnt,Cnt,from[maxn],flow[maxn],cost[maxn];bool vis[maxn];vector <int> v[maxn];queue <int> Q;void Add(int x,int y,int cap,int cost){v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0,cost);v[y].push_back(cnt); edgs[cnt++] = E(x,0,0,-cost);}bool SPFA(){for (int i = 0; i <= T; i++) cost[i] = INF,vis[i] = 0;vis[S] = 1; Q.push(S);flow[S] = INF; cost[S] = 0;while (!Q.empty()){int k = Q.front(); Q.pop(); vis[k] = 0;for (int i = 0; i < v[k].size(); i++){E e = edgs[v[k][i]];if (e.cap == e.flow) continue;if (cost[e.to] > cost[k] + e.cost){cost[e.to] = cost[k] + e.cost;flow[e.to] = min(flow[k],e.cap - e.flow);from[e.to] = v[k][i];if (!vis[e.to]) vis[e.to] = 1,Q.push(e.to);}}}return cost[T] != INF;}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> n >> m; s = 2*n + 1; t = s + 1; S = t + 1; T = S + 1; Add(s,0,m,0);for (int i = 1; i <= n; i++){int x; scanf("%d",&x);Add(i,T,x,0); Add(S,i + n,x,0);Add(0,i,INF,0); Add(i + n,t,INF,0);}for (int i = 1; i < n; i++)for (int j = i + 1; j <= n; j++){int x; scanf("%d",&x);if (x == -1) continue;Add(i + n,j,INF,x);}Add(t,s,INF,0); int Ans = 0;while (SPFA()){Ans += flow[T]*cost[T];for (int x = T; x != S; x = edgs[from[x]^1].to){edgs[from[x]].flow += flow[T];edgs[from[x]^1].flow -= flow[T];}}cout << Ans;return 0;}

0 0
原创粉丝点击