HDU5545-The Battle of Guandu

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
  
  
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
 

Source
 

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 long
const 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());
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值