• [bzoj1040]: [ZJOI2008]骑士


    http://www.lydsy.com/JudgeOnline/problem.php?id=1040

    题意:有n个骑士,每个骑士都有一个憎恶的人不能和他同时选,每个骑士有一个战斗力,求最大的战斗力的和

    n<=1,000,000   数据范围有点吓人

    很明显这是一个无向环带外向树的图。

    把环找出来,然后断掉其中的一条边(这样就成了树),分别以这条边的两头为根,并且强制不选另一头,用树形dp算一下答案,取最大值即可。

    f[i][0] 表示点i不选的最大战斗力,f[i][1]表示点i选了的战斗力

    f[i][1]=sigma(f[v][0]) v是i的儿子

    f[i][0]=sigma(max(f[v][0],f[v][1]))

    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define MAXN 1000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int s[MAXN+5];
    ll f[MAXN+5][2];
    int n,rt1,rt2,cnt=1;
    ll ans=0,maxn;
    struct edge{
        int to,next;
    }e[MAXN*2+5];
    int head[MAXN+5];
    bool b[MAXN+5];
    bool vis[MAXN+5];
    
    inline void ins(int f,int t)
    {
        e[++cnt].next=head[f];
        head[f]=cnt;
        e[cnt].to=t;
    }
    
    void dfs(int x,int fa)
    {
        b[x]=1;
        for(int i=head[x];i&&!rt1;i=e[i].next)
        {
            int v=e[i].to;
            if(v!=fa)
            {
                if(b[v]) {rt1=x;rt2=v;e[i].to=e[i^1].to=-1;return;}
                dfs(v,x);
            }
        }
    }
    
    void dp(int x,int fa,int ban)
    {
        b[x]=1;if(x!=ban)f[x][1]=s[x];else f[x][1]=0;f[x][0]=0;
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v!=-1&&v!=fa)
            {
                dp(v,x,ban);
                f[x][1]+=f[v][0];
                f[x][0]+=max(f[v][1],f[v][0]);
            }
        }
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            s[i]=read();int x=read();
            ins(i,x);ins(x,i);
        }
        for(int i=1;i<=n;i++)
            if(!b[i])
            {
                rt1=rt2=0;dfs(i,0);
                dp(rt1,0,rt2);
                maxn=max(f[rt1][1],f[rt1][0]);
                dp(rt2,0,rt1);
                maxn=max(maxn,max(f[rt2][1],f[rt2][0]));
                ans+=maxn;
            }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Yslow-23条规则
    ASP.Net MVC多语言
    Java笔记--反射机制
    Java笔记--常用类
    Java笔记--多线程
    Java--IO流
    Java笔记--枚举&注解
    Java笔记--泛型
    Java笔记--异常
    Java笔记--集合
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1040.html
Copyright © 2020-2023  润新知