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

    题目链接:

    题解:

    早在寒假就讲了这题了,现在才A掉。话说如果题目上给出的关系就是一棵树的话,显然就是没有上司的舞会。但我们看样例就不是一棵树,而是成环的关系。不过也无妨,我们遇到环时同样可以解决,你在dfs找环的时候就可以记录一下任意两个在环上的点,然后把环断开,以这两个点为根分别跑树形dp。树形dp的状态定义也很明显:设dp[i][0/1]表示以i为根,选或不选它本身所获得的最大值。转移方程就呼之欲出了:dp[i][0]+=max(dp[son[i][1],dp[son[i]][0])。加上它的儿子选或不选的最大值。dp[i][1]+=dp[son[i]][0]。他选了他的儿子们都不能选。最后每个连通块内加上的都是dp[root][0]的最大值。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    int n;
    int x,power[maxn];
    struct node{
        int nxt,to;
    }edge[maxn*2];
    int cnt=1,head[maxn];
    long long dp[maxn][2];
    void add(int x,int y){
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;
        head[x]=cnt;
    }
    bool vis[maxn];
    int edge_num,point_num1,point_num2;
    long long sum;
    void circle(int x,int f){
        vis[x]=true;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(v==f) continue;
            if(!vis[v]) circle(v,x);
            else{
                edge_num=i;
                point_num1=x;//记录在环上两点的信息 
                point_num2=v;
            }
        }
    }
    void dfs(int x,int f){
        dp[x][1]=power[x];
        dp[x][0]=0;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].to;
            if(v==f) continue;
            if(i==edge_num||i==(edge_num^1)) continue;
            dfs(v,x);
            dp[x][0]+=max(dp[v][0],dp[v][1]);
            dp[x][1]+=dp[v][0];
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&power[i],&x);
            add(i,x);add(x,i);
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                circle(i,0);
                dfs(point_num1,0);
                long long ans=dp[point_num1][0];
                dfs(point_num2,0);
                sum+=max(ans,dp[point_num2][0]);
            }
        }
        printf("%lld
    ",sum);
        return 0;
    }
    View Code
  • 相关阅读:
    剑指OFFER之包含min函数的栈
    剑指OFFER之二叉树的镜像
    关于【最长递增子序列(LIS)】
    题目1113:二叉树
    剑指OFFER之字符串的排列
    题目1120:全排列
    题目1460:Oil Deposit
    题目1459:Prime ring problem
    剑指OFFER之二叉树中和为某一值的路径
    python 线程、进程
  • 原文地址:https://www.cnblogs.com/LJB666/p/11716768.html
Copyright © 2011-2022 走看看