zoukankan      html  css  js  c++  java
  • BZOJ1040: [ZJOI2008]骑士

    【传送门:BZOJ1040


    简要题意:

      给出n个人,每个人都有自己的战力值和最讨厌的人,选出若干个人使得这些人中的每一个人所讨厌的人都不在这些人中,求出最大战力值


    题解:

      一看,这好像是森林,再看,还有环!

      一开始看,还不会做,结果hanks_o来D飞了我,说这道题很简单

      好吧,确实挺简单的。。

      将讨厌的人和被讨厌的人连双向边

      首先一棵一棵树的求,对于一棵树,先把环给找出来(因为题目中每个人只有一个讨厌的人,所以每棵树中最多只有一个环),然后在环中找一条边将环切断,并且切断的这条边的两点x,y不能同时选择,使得这棵树成为真正意义上的树,然后进行树形DP,对于i点,f[i][0]表示不选第i个点的最大收益,f[i][1]表示选i点的最大收益,然后对于每棵树将x拉到根处,再把y拉到根处,分别求出f[x][1],f[y][1],取最大值,这个最大值就是这棵树的最大收益

      然后把每棵树的收益都加起来就是答案

      注意:要加long long

      UPD(2018.10.5):实际上,这题是基环树森林+DP,但是当时不会,可是操作跟基环树的操作没多大差别


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    LL s[1100000];
    struct node
    {
        int x,y,next,other;
    }a[2100000];int len,last[1100000];
    void ins(int x,int y)
    {
        int k1=++len,k2=++len;
        a[k1].x=x;a[k1].y=y;
        a[k1].next=last[x];last[x]=k1;
        a[k2].x=y;a[k2].y=x;
        a[k2].next=last[y];last[y]=k2;
        a[k1].other=k2;
        a[k2].other=k1;
    }
    bool v[1100000];
    LL f[1100000][2];
    int X,Y,K;
    void bt(int x,int fa)
    {
        v[x]=true;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y==fa) continue;
            if(v[y]==true){X=x;Y=y;K=k;continue;}
            bt(y,x);
        }
    }
    void dp(int x,int fa)
    {
        f[x][0]=0;f[x][1]=s[x];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y==fa) continue;
            if(k==K||k==a[K].other) continue;
            dp(y,x);f[x][0]+=max(f[y][0],f[y][1]);f[x][1]+=f[y][0];
        }
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d%d",&s[i],&x);
            ins(i,x);
        }
        memset(v,false,sizeof(v));
        LL ans=0,t1,t2;
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)
        {
            if(v[i]==false)
            {
                bt(i,0);
                dp(X,0);t1=f[X][0];
                dp(Y,0);t2=f[Y][0];
                ans+=max(t1,t2);
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    postmessage
    input、textarea等输入框输入中文时,拼音在输入框内会触发input事件的问题
    h5判断设备是ios还是android
    js获取地址栏的参数
    BootStrap 响应式布局
    前端框架 BootStrap 快速入门(Hallo Word)
    HTML + CSS + JavaScript 实现注册页面信息验证(表单验证)
    HTML + CSS + JavaScript 实现勾选动态表格中的记录
    JavaScript常见的事件监听
    HTML + CSS + JavaScript 实现简单的动态表格
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8384322.html
Copyright © 2011-2022 走看看