标签:
The Battle of Guandu
Time Limit: 1 Sec
Memory Limit: 256 MB
无
2
2 3
2 3
1 1
1 1
0 1 2
1 1
1
1
1
2
Sample Output
Case #1: 1
Case #2: -1
题意
在一场战争中,有m(<=100000)个战场和n(<=100000)个村 庄,每个战场有一个重要度,重要度为0表示在这个战场己方输赢无所谓,重要度为1表示己方不能输,重要度为2表示己方必须胜出,己方获得战争的最终胜利当 且仅当己方在每个战场的战果均不违背其重要度,每个战场输赢的判据只有人数,人多的一方胜出,若两方人数相同则打平,对于第i个村庄,每花费c[i]的代 价能够征用一个人派到己方x[i]战场,同时有一个人会跑到敌方y[i]战场,问己方能否获得战争的最终胜利,若能,求出最小代价。
题解:
建图跑spfa就好,如果你考虑每个战场我方人数-敌方人数的数量的话,整个战场的人数实际上是守恒的。你可以花费c[i]代价,使得x[i]加一个人,y[i]减一个人。那么我们就建边跑最短路就好啦,让不重要的战场当成源点,重要的战场当成你要求的最短路就好了
d[i]表示从不重要战场拉一个人到i战场需要的最小代价,只要拉一个人就会胜利
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<queue> #include<vector> using namespace std; #define maxn 100005 long long inf = 999999999999999LL; int x[maxn]; int y[maxn]; long long c[maxn]; int p[maxn]; int vis[maxn]; long long d[maxn]; vector<pair<int,long long> >G[maxn]; int main() { int t;scanf("%d",&t); for(int cas = 1;cas <= t;cas++) { int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) G[i].clear(); for(int i=1;i<=n;i++) scanf("%d",&x[i]); for(int i=1;i<=n;i++) scanf("%d",&y[i]); for(int i=1;i<=n;i++) scanf("%lld",&c[i]); for(int i=1;i<=m;i++) scanf("%d",&p[i]); for(int i=1;i<=n;i++) { if(p[x[i]]==0)continue; G[y[i]].push_back(make_pair(x[i],c[i])); } queue<int> Q; for(int i=1;i<=m;i++) { if(p[i]==0) { d[i]=0; vis[i]=1; Q.push(i); } else { d[i]=inf; vis[i]=0; } } while(!Q.empty()) { int now = Q.front(); Q.pop(); vis[now]=0; for(int i=0;i<G[now].size();i++) { int v = G[now][i].first; if(d[v]>G[now][i].second + d[now]) { d[v] = G[now][i].second + d[now]; if(vis[v])continue; Q.push(v); vis[v]=1; } } } long long ans = 0; int flag = 0; for(int i=1;i<=m;i++) { if(p[i]==2) { if(d[i]==inf) { flag = 1; break; } ans += d[i]; } } if(flag) printf("Case #%d: -1\n",cas); else printf("Case #%d: %lld\n",cas,ans); } }
2015南阳CCPC F - The Battle of Guandu 多源多汇最短路
标签:
原文地址:http://www.cnblogs.com/qscqesze/p/4901547.html