HDU5545-The Battle of Guandu

来源:互联网 发布:软件自学网站大全 编辑:程序博客网 时间:2024/05/17 07:49

The Battle of Guandu

                                                                            Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
                                                                                                         Total Submission(s): 360    Accepted Submission(s): 152


Problem Description
In the year of 200, two generals whose names are Cao Cao and Shao Yuan are fighting in Guandu. The battle of Guandu was a great battle and the two armies were fighting at M different battlefields whose numbers were 1 to M. There were also N villages nearby numbered from 1 to N. Cao Cao could train some warriors from those villages to strengthen his military. For village i, Cao Cao could only call for some number of warriors join the battlefield xi. However, Shao Yuan's power was extremely strong at that time. So in order to protect themselves, village i would also send equal number of warriors to battlefield yi and join the Yuan Shao's Army. If Cao Cao had called for one warrior from village i, he would have to pay ci units of money for the village. There was no need for Cao Cao to pay for the warriors who would join Shao Yuan's army. At the beginning, there were no warriors of both sides in every battlefield.

As one of greatest strategist at that time, Cao Cao was considering how to beat Shao Yuan. As we can image, the battlefields would have different level of importance wi. Some of the battlefields with wi=2 were very important, so Cao Cao had to guarantee that in these battlefields, the number of his warriors was greater than Shao Yuan's. And some of the battlefields with wi=1 were not as important as before, so Cao Cao had to make sure that the number of his warriors was greater or equal to Shao Yuan's. The other battlefields with wi=0 had no importance, so there were no restriction about the number of warriors in those battlefields. Now, given such conditions, could you help Cao Cao find the least number of money he had to pay to win the battlefield?
 

Input
The first line of the input gives the number of test cases, T(1T30)T test cases follow.

Each test case begins with two integers N and M(1N,M105) in one line.

The second line contains N integers separated by blanks. The ith integer xi(1xiM) means Cao Cao could call for warriors from village i to battlefield xi.

The third line also contains N integers separated by blanks. The ith integer yi(1yiM) means if Cao Cao called some number of warriors from village i, there would be the same number of warriors join Shao Yuan's army and fight in battlefield yi.

The next line contains N integers separated by blanks. The ith integer ci(0ci105) means the number of money Cao Cao had to pay for each warrior from this village.

The last line contains M integers separated by blanks. The ith number wi(wi0,1,2) means the importance level of ith battlefield.
 

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the least amount of money that Cao Cao had to pay for all the warriors to win the battle. If he couldn't win, y=1.
 

Sample Input
22 32 31 11 10 1 21 11112
 

Sample Output
Case #1: 1Case #2: -1
 

Source
The 2015 China Collegiate Programming Contest
 

Recommend
wange2014
 

题意:有n个村庄和m个战场,从第i个村庄花费ci能让一个人去曹操的xi战场,一个人去袁绍的yi战场,对于每个战场有一个战略意义wi(0/1/2),为0的话输赢无所谓,为1的话不能输,为2必须赢,求最小花费使得曹操能赢整个大局,无解输出-1

解题思路:假设一开每个战场双方的人数都是0,那么对于要赢的战场要保证曹操的人数比袁绍的人数多一个就可以了。因为每个村庄派出的人数是相等的。所以战场上双方总人数是相等的。但是要赢的战场人要多,那么只有可以输的战场人是少的。那么对于每个村庄派出去的人可以看成是从bi战场调用一个人去ai战场花费了ci。重要值为0的战场可以被调兵。所以就跑一个多源最短路,求出所有重要值为2的点的最小费用。对于重要值为1的战场,可以当成有兵经过这里或者没有经过这里。最后累加答案时只需累加重要值为2的战场


#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <queue>#include <vector>#include <bitset>using namespace std;#define LL long longconst LL INF = 0x3f3f3f3f3f3f3f3f;const double pi = acos(-1.0);const double eps = 1e-8;int t, n, m;int s[100050], nt[100050], e[100050];LL l[100050], dis[100050],c[100050];int x[100050], visit[100050], y[100050],  w[100050];struct node{int id;LL dis;friend bool operator < (node a, node b){return a.dis > b.dis;}};LL Dijkstra(){memset(visit, 0, sizeof visit);priority_queue<node>q;node pre, nt1;for (int i = 1; i <= m; i++){if (dis[i] == 0){pre.id = i, pre.dis = 0;q.push(pre);}}while (!q.empty()){pre = q.top();q.pop();visit[pre.id] = 1;for (int i = s[pre.id]; ~i; i=nt[i]){int ee = e[i];if (visit[ee]) continue;if (dis[ee]>dis[pre.id] + l[i]){dis[ee] = dis[pre.id] + l[i];nt1.id = ee;nt1.dis = dis[ee];q.push(nt1);}}}LL sum = 0;for (int i = 1; i <= m; i++){if (w[i] == 2){if (dis[i] ==INF) return -1;sum += dis[i];}}return sum;}int main(){scanf("%d",&t);int cas = 1;while (t--) {scanf("%d%d", &n, &m);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", &w[i]);int cnt = 1;for (int i = 1; i <= m; i++) dis[i] = INF;memset(s, -1, sizeof s);for (int i = 1; i <= n; i++){nt[cnt] = s[y[i]], e[cnt] = x[i], l[cnt] = c[i], s[y[i]] = cnt++;if (w[y[i]] == 0) dis[y[i]] = 0;}printf("Case #%d: %lld\n", cas++,Dijkstra());}}

0 0
原创粉丝点击