• 2015南阳CCPC F


    The Battle of Guandu

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    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

    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.

    Output

    For each test case, output one line containing Case #x:, where x is the test case number (starting from 1). Then output 4 lines with 4 characters each. indicate the recovered board.

    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

    HINT

    题意

    在一场战争中,有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
    ",cas);
            else
                printf("Case #%d: %lld
    ",cas,ans);
        }
    }
  • 相关阅读:
    Android 的快速增长让一些开发人员担忧 狼人:
    Android程序开发入门教程 狼人:
    2010:Android 商机之年 狼人:
    控制力的较量 Android上的博弈 狼人:
    深度解析Windows Phone 7 开发 狼人:
    图解iPhone开发入门教程 狼人:
    用Android LiveCD体验Android 操作系统的魅力 狼人:
    Android 教程之实现动作感应技术 狼人:
    Android版多功能日历,欢迎大家测试 狼人:
    iPhone、Windows Mobile、Symbian、Android移动开发前景分析 狼人:
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4901547.html
Copyright © 2020-2023  润新知