• 洛谷P2607 [ZJOI2008]骑士


    题目描述:

    题意:给定每个人的战斗力和它最讨厌的人,组建一个队伍,要求求出使得队伍战斗力总和的最大值。

    思路分析:

      其实看到这道题我们应该就能联想到我们在之前刚学树形dp时做的一道叫“没有上司的舞会”的题目,这道题和那道题十分相似,只不过这道题可能会出现环的情况,而且每个人都有了权值。

      既然我们联想到了我们做过的题,我们就可以用那道题的方法来应对这道题,即树形DP,针对于环的情况,我们可以把环的其中一条边断开,这样就形成了树的结构,但是要注意环断开的两边的两个节点不可以同时被选。注意了以上要素后,我们就可以解决这道题了,我们先找到环,再环要断开的两边进行dp,注意强制让两边的点不能同时在一个组中,用dp[i][0]表示i节点不选,dp[i][1]表示该节点被选,相邻节点不能同时被选,于是我们有:dp[i][0]=sigema(max(dp[i][0],dp[i][1])),dp[i][1]=sigema(dp[i][0]);之后递归统计答案即可。注意开long long。

      另外,数组一般真的不要开得太大,我刚开始开了1e8的数组,结果在洛谷上编译都过不去,就出现下图的情况:

    所以开数组千万小心。

    上代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=2e6+10;
     6 long long ans,dp[N][2];
     7 struct Node{
     8     int next,to;
     9 }e[N];
    10 int Head[N],fa[N],vis[N],val[N],tot,root;
    11 void Add(int x,int y){  //加边函数 
    12     e[++tot].to=y;
    13     e[tot].next=Head[x];
    14     Head[x]=tot;
    15 }
    16 void Dp(int x){   //选定起点后开始动规  
    17     vis[x]=1;
    18     dp[x][0]=0;dp[x][1]=val[x];
    19     for(int i=Head[x];i;i=e[i].next){
    20         int v=e[i].to;
    21         if(v!=root){
    22             Dp(v);
    23             dp[x][0]+=max(dp[v][1],dp[v][0]);
    24             dp[x][1]+=dp[v][0];
    25         }
    26         else{   //到了删除边的另一端,强制拆开 
    27             dp[v][1]=-N;
    28         }
    29     }
    30 }
    31 void find(int x){
    32     vis[x]=1;
    33     root=x;
    34     while(!vis[fa[root]]){  //找到环的位置 
    35         root=fa[root];
    36         vis[root]=1;
    37     }
    38     Dp(root);  //分别跑环中选定边两边的节点,在Dp部分有关于不让他们在一起的判断 
    39     long long t=max(dp[root][0],dp[root][1]);
    40     vis[root]=1;
    41     root=fa[root];
    42     Dp(root);
    43     ans+=max(t,max(dp[root][0],dp[root][1]));
    44     return;
    45 }
    46 int main(){
    47     int n;
    48     scanf("%d",&n);
    49     for(int i=1;i<=n;++i){
    50         int x;
    51         scanf("%d%d",&val[i],&x);
    52         Add(x,i);  //让他讨厌的人指向他 
    53         fa[i]=x;
    54     }
    55     for(int i=1;i<=n;++i){
    56         if(!vis[i]) find(i);  //一个环一个环的查 
    57     }
    58     printf("%lld
    ",ans);  //输出答案 
    59     return 0;
    60 } 
    View Code
  • 相关阅读:
    css实现鼠标移入table时出现滚动条且table内容不移位
    SASS学习笔记
    html5--canvas学习笔记
    在iframe里调用parent.func()引出的js函数运行在它们被定义的作用域里,而不是它们被执行的作用域里
    css background-position:x% y%
    js十进制等互相转换
    jsp中的动作元素:<jsp:plugin>
    终于有时间写代码了
    OK 开始实践书上的项目一:即使标记
    我没有忘记敲代码
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12769229.html
Copyright © 2020-2023  润新知