• HYSBZ 1040 骑士 (基环外向树DP)


    Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各
    界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境
    中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一
    个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一
    些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出
    征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有
    的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的
    情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战
    斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。

    Input

      第一行包含一个正整数N,描述骑士团的人数。接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力
    和他最痛恨的骑士。

    Output

      应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。

    Sample Input3 10 2 20 3 30 1

    Sample Output30Hint

    N ≤ 1 000 000,每名骑士的战斗力都是不大于 1 000 000的正整数。

    题目大意:

    分别给你n个骑士的战斗力和他痛恨的骑士(有且仅有一个且不是自己)。要你组织一个军团,使得军团战斗力最强,且军团中没有一个人是另一个人所痛恨的。军团战斗力极为骑士战斗力之和。

    看到题目,就想到了之前做到的摘苹果问题(没有上司的聚会)。相邻等级的苹果不能同时被采摘。

    DP表达式即为:dp[i][0]=∑max(dp[son][0],dp[son][1]);dp[i][1]=∑dp[son][0];

    但是这道题是可能出现环(环上至少有3个元素)的。

    如果出现环,则删去环中的一条边,从这条边的两点分别做DP,最后答案便是max(dp[st][0],dp[en][0]),即两点不可能同时取到。

    此题可能有多个连通分量,且并非所有连通分量都一定有环(有互相痛恨的骑士)(这导致一条无向边可能存储了两次,要删去一个),这些在代码中都要注意。

    答案要lol,链式前向星要开双倍数组!

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=1000000;
    
    int fight[maxn+5];
    
    int to[maxn*2+5];
    int nex[maxn*2+5];
    int head[maxn+5];
    int cnt;
    
    void addedge(int u,int v)
    {
        to[cnt]=v;
        nex[cnt]=head[u];
        head[u]=cnt++;
    }
    
    bool isedge(int u,int v)
    {
        for(int i=head[u];i!=-1;i=nex[i])
        {
            if(to[i]==v)
                return true;
        }
        return false;
    }
    
    int vis1[maxn+5];
    int st,en;
    
    void dfs1(int x,int fa)
    {
        vis1[x]=1;
        for(int i=head[x];i!=-1;i=nex[i])
        {
            if(to[i]!=fa)
            {
                if(!vis1[to[i]])
                    dfs1(to[i],x);
                else
                {
                    st=x;
                    en=to[i];
                }
            }
        }
    }
    
    long long dp[maxn+5][2];
    int vis2[maxn+5];
    
    void dfs2(int x)
    {
        vis2[x]=1;
        bool flag=false;
        for(int i=head[x];i!=-1;i=nex[i])
        {
            if(!vis2[to[i]]&&!((x==st&&to[i]==en)||(x==en&&to[i]==st)))
            {
                dfs2(to[i]);
                flag=true;
                dp[x][1]+=dp[to[i]][0];
                dp[x][0]+=max(dp[to[i]][0],dp[to[i]][1]);
            }
        }
        dp[x][1]+=1LL*fight[x];
        if(!flag)
            dp[x][1]=1LL*fight[x];
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            memset(head,-1,sizeof(head));
            cnt=0;
            for(int i=1,a,b;i<=n;i++)
            {
                scanf("%d%d",&a,&b);
                fight[i]=a;
                if(!isedge(i,b))
                {
                    addedge(i,b);
                    addedge(b,i);
                }
            }
    
            long long ans=0;
            memset(vis1,0,sizeof(vis1));
            for(int i=1;i<=n;i++)
            {
                if(!vis1[i])
                {
                    st=-1,en=-1;
                    dfs1(i,-1);
                    //printf("%d %d
    ",st,en);
                    if(st==-1&&en==-1)
                    {
                        memset(vis2,0,sizeof(vis2));
                        memset(dp,0,sizeof(dp));
                        dfs2(i);
                        ans+=max(dp[i][0],dp[i][1]);
                    }
                    else
                    {
                        memset(vis2,0,sizeof(vis2));
                        memset(dp,0,sizeof(dp));
                        dfs2(st);
                        long long temp=dp[st][0];
                        memset(vis2,0,sizeof(vis2));
                        memset(dp,0,sizeof(dp));
                        dfs2(en);
                        //printf("%d %d
    ",temp,dp[en][0]);
                        ans+=max(temp,dp[en][0]);
                    }
                }
            }
    
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    WindowsForm:百科
    App-应用程式:百科
    ASP.NET:目录
    ASP.NET:百科
    操作平台:.NET
    DB-触发器:百科
    DB-DatabaseLink:百科
    5090 众数
    计数排序
    归并排序
  • 原文地址:https://www.cnblogs.com/acboyty/p/9784918.html
Copyright © 2020-2023  润新知