The Battle of Guandu HDU - 5545

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(1≤T≤30). T test cases follow.

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

The second line contains N integers separated by blanks. The ith integer xi(1≤xi≤M) 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(1≤yi≤M) 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(0≤ci≤105) 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(wi∈0,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

题意:给出n个村庄,m个战场,对于每一个村庄如果选一个人,那么他会前往x[i]战场,并且还会有一个人前往y[i]战场,每一个战场有一个值,要求值为2的战场你的兵力要多于敌方,值为1的战场要大于等于,值为0的不要求,
做法:设每个战场有一个值为双方兵力差,那么值为2的战场值至少为1,值为1的至少为0,对于每一个村庄,选一个人相当于x[i]战场+1,y[i]战场-1,相当于从y[i]战场拿一个人到x[i]战场,这样对于每一个值为2的战场都会有一条路径,终点肯定在值为0的战场,所以这题就可以把值为0的战场作为起点,y[i]到x[i]连边权为c[i],跑最短路。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
int x[N],y[N],c[N];
vector<pair<int,int> > G[N];
long long d[N];

int main(){
    int T;
    cin >> T;
    for(int kase = 1;kase <= T;kase ++){
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i = 1;i <= n;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("%d",&c[i]);
        for(int i = 1;i <= n;i ++){
            G[y[i]].push_back({x[i],c[i]});
        }
        memset(d,0x3f,sizeof(d));
        vector<int> vp;
        priority_queue<pair<long long,int>,vector<pair<long long,int> >,greater<pair<long long,int> > >que;
        for(int i= 1;i <= m;i ++){
            int now;
            scanf("%d",&now);
            if(now == 2) vp.push_back(i);
            else if(now == 0) {d[i] = 0;que.push({0,i});}
        }
        while(!que.empty()){
            pair<long long,int> now;
            now = que.top();
            que.pop();
            long long dd= now.first;
            int u = now.second;
            if(d[u] < dd) continue;
            for(int i= 0;i < G[u].size();i ++){
                int v = G[u][i].first;
                if(d[v] > d[u]+G[u][i].second){
                    d[v] = d[u]+G[u][i].second;
                    que.push({d[v],v});
                }
            }
        }
        long long ans = 0;
        bool tmp = true;
        for(int i = 0;i < vp.size();i ++){if(d[vp[i]] == d[0]) tmp = false;else ans += d[vp[i]];}
        if(tmp) printf("Case #%d: %lld\n",kase,ans);
        else printf("Case #%d: -1\n",kase);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zstu_zy/article/details/81062469