zoukankan      html  css  js  c++  java
  • 1083. 【GDOI2006】拯救亚特兰蒂斯

    Description

    亚特兰蒂斯人激怒了众神,众神之王宙斯决定要好好教化他们。这时,一位居心叵测的 bug 魔王看准了时机,打着“教化亚特兰蒂斯人”的旗号,暗地里策划了一个极具野心的阴谋:铲平亚特兰蒂斯。善良的宙斯并没有发现他的阴谋,草率地批准了他这次“教化”行动,于是一场危机就要降临亚特兰蒂斯了……

    幸好亚特兰蒂斯拥有一位相当优秀的先知 Cubic,他发现了 bug 魔王的阴谋,并了解到bug魔王会派出N种怪物来入侵亚特兰蒂斯,现在就要想办法对付这N种怪物。Cubic 还了解到,每一种怪物都对应一种剑术和一种法术,这种怪物可以被这对应的剑术打败,也可以被对应的法术打败。不同的怪物可能对应不同的剑术和法术,而一种剑术或法术可以击败多种怪物。只要 Cubic 得到某怪物的信息,他就可以知道对应的剑术和法术,不会只知其一。

    亚特兰蒂斯里最优秀的剑术师是 RC,最优秀的法术师是 Aesop,这次为了保护亚特兰蒂斯,他们都愿意挺身而出。但问题是他们并不会这些特定的剑术和法术,必须抓紧时间学习。但由于学习新剑术或新法术需要闭关学习,为了避免 bug 魔王搞奇袭,必须至少留下其中一个专门看守,于是他们两个就不能同时去学习了。

    现在 bug 魔王已经屯好兵了,时间所剩无几,他们必须在最短的时间内学会相应的剑术和法术,以打败所有的怪物。学习一种剑术或一种法术所需要的时间都为 1。现在问题是,他们到底应该学习哪种剑术和法术,才能在最短时间内拥有打败所有怪物的能力呢?

    即便是再聪明的 Cubic 这次都头痛了。于是他找到了你——亚特兰蒂斯的顶级技术顾问,来帮他解决这个问题。所以,拯救亚特兰蒂斯的重任就交给你了。

    Solution

    首先先处理输入,\(\mathrm{map}\) 或者哈希都可以。

    处理出每个怪物可以被哪种剑术和法术击败,如果有怪物无法被击败,那么无解。

    将每个怪物的剑术和法术连边,那么题目变成求点集的最小覆盖,求最大匹配即可。

    建超级源和超级汇,源点连向剑术,法术连向汇点。跑匈牙利或者网络流。

    Code

    #include<map>
    #include<queue>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #define mo 19260817
    #define N 10005
    #define inf 2147483647
    using namespace std;
    struct node
    {
        int to,next,flow;
    }a[N<<2];
    map<string,int> monster;
    int n,m1,m2,num,tot,S,T,ans,atk[N][3],head[N<<1],cur[N<<1],deep[N<<1];
    char ch[20];
    bool b[N];
    void add(int x,int y)
    {
        a[++tot].to=y;a[tot].flow=1;a[tot].next=head[x];head[x]=tot;
        a[++tot].to=x;a[tot].flow=0;a[tot].next=head[y];head[y]=tot;
    }
    bool bfs()
    {
        memset(deep,0,sizeof(deep));
        queue<int> q;
        deep[S]=1;q.push(S);
        while (!q.empty())
        {
            int x=q.front();q.pop();
            for (int i=head[x];i;i=a[i].next)
            {
                int y=a[i].to;
                if (!deep[y]&&a[i].flow)
                {
                    deep[y]=deep[x]+1;
                    q.push(y);
                    if (y==T) return true;
                }
            }
        }
        return false;
    }
    int dfs(int x,int flow)
    {
        if (x==T) return flow;
        int res=0;
        for (int &i=cur[x];i;i=a[i].next)
        {
            int y=a[i].to;
            if (a[i].flow&&deep[y]==deep[x]+1)
            {
                int fl=dfs(y,min(flow,a[i].flow));
                if (!fl) continue;
                a[i].flow-=fl;a[i^1].flow+=fl;
                res+=fl;flow-=fl;
                if (!flow) break;
            }
        }
        return res;
    }
    int main()
    {
        freopen("T3.in","r",stdin);
        freopen("T3.out","w",stdout);
        while (true)
        {
            scanf("%d%d%d",&n,&m1,&m2);
            if (n==-1&&m1==-1&&m2==-1) break;
            monster.clear();
            for (int i=1;i<=n;++i)
            {
                string s="";
                scanf("%s",ch);
                int len=strlen(ch);
                for (int j=0;j<len;++j)
                    s+=ch[j];
                monster[s]=i;
            }
            memset(b,false,sizeof(b));
            for (int i=1;i<=m1;++i)
            {
                scanf("%s",ch);
                scanf("%d",&num);
                for (int j=1;j<=num;++j)
                {
                    string s="";
                    scanf("%s",ch);
                    int len=strlen(ch);
                    for (int k=0;k<len;++k)
                        s+=ch[k];
                    atk[monster[s]][1]=i;
                    b[monster[s]]=true;
                }
            }
            for (int i=1;i<=m2;++i)
            {
                scanf("%s",ch);
                scanf("%d",&num);
                for (int j=1;j<=num;++j)
                {
                    string s="";
                    scanf("%s",ch);
                    int len=strlen(ch);
                    for (int k=0;k<len;++k)
                        s+=ch[k];
                    atk[monster[s]][2]=i;
                    b[monster[s]]=true;
                }
            }
            bool flag=true;
            for (int i=1;i<=n;++i)
                if (!b[i])
                {
                    printf("Poor Atlantis!\n");
                    flag=false;
                    break;
                }
            if (!flag) continue;
            tot=1;
            memset(head,0,sizeof(head));
            S=m1+m2+1;T=m1+m2+2;
            for (int i=1;i<=n;++i)
                if (atk[i][1]&&atk[i][2]) add(atk[i][1],atk[i][2]+m1);
            for (int i=1;i<=m1;++i)
                add(S,i);
            for (int i=1;i<=m2;++i)
                add(i+m1,T);
            ans=0;
            while (bfs())
            {
                for (int i=1;i<=m1+m2+2;++i)
                    cur[i]=head[i];
                ans+=dfs(S,inf);
            }
            printf("%d\n",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    [Matlab.Matrix] 作为判断条件
    [Matlab.GUI] 学习小结
    [Modelsim] 初识
    [Matlab] isnan
    [Matlab] round
    [VS2012] 无法查找或打开 PDB 文件
    [Matlab.GUI]初识
    表格特效代码全集中
    JAVASCRIPT基础
    第4天:调用样式表
  • 原文地址:https://www.cnblogs.com/Livingston/p/15824146.html
Copyright © 2011-2022 走看看