• codeforces 337D 树形DP Book of Evil


    原题直通车: codeforces 337D Book of Evil

    题意:一棵n个结点的树上可能存在一个Evil,Evil危险范围为d,即当某个点与它的距离x<=d时,那么x是危险的。

          现已知道有m个点是危险的,问那个Evil可能存的点有多少。

    分析: 昨晚傻X地暴力提交,自然得到的是TLE。今天看一神的代码才突然明白……

          跟以往的题一样,两个DFS就可求出答案。

          第一个DFS搜出所有危险点,并求出枝干上的点到最远的危险点的距离。

          第二次DFS再往回遍历。具体的参考代码。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int maxn=111111;
    vector<int>Tree[maxn];
    int deep[maxn];
    int n,m,d,ans;
    bool vis[maxn],vid[maxn];
    void DFS(int cnt){
        vis[cnt]=true;
        deep[cnt]=-1;
        if(vid[cnt]) deep[cnt]=0;
        int len=Tree[cnt].size();
        for(int i=0;i<len;++i){
            int son=Tree[cnt][i];
            if(vis[son]) continue;
            DFS(son);
            deep[cnt]=max(deep[cnt],deep[son]+(deep[son]==-1?0:1));
        }
    }
    void DFS_DP(int cnt,int up){ 
        if(up<=d&&deep[cnt]<=d) ans++;
        vis[cnt]=true;
        int len=Tree[cnt].size();
        vector<int>P,S;
        for(int i=0;i<len;++i) {
            int son=Tree[cnt][i];
            if(vis[son]) continue;
            P.push_back(deep[son]==-1?-1:(deep[son]+2));//兄弟结点-->父亲结点-->自身,所以得+2步
            S.push_back(son);
        }
        int ls=S.size();
        if(ls==0) return;
        vector<int>L(ls),R(ls);
        int Max=-1; //下面两循环是为了求出所有兄弟结点的最大deep值。
        for(int i=0;i<ls;++i){
            L[i]=Max;
            if(P[i]>Max) Max=P[i];
        }
        Max=-1;
        for(int i=ls-1;i>=0;--i){
            R[i]=Max;
            if(P[i]>Max) Max=P[i];
        }
        for(int i=0;i<ls;++i){
            int newup=(up==-1?-1:(up+1));
            newup=max(newup,max(L[i],R[i]));
            if(vid[cnt]&&newup<1) newup=1;
            DFS_DP(S[i],newup);
        }
    }
    int main(){
        cin>>n>>m>>d;
        for(int i=1;i<=m;++i){
            int a; cin>>a; vid[a]=true;
        }
        for(int i=1;i<n;++i) {
            int a,b; cin>>a>>b;
            Tree[a].push_back(b);
            Tree[b].push_back(a);
        }
        DFS(1);
        memset(vis,false,sizeof(vis));
        ans=0;
        DFS_DP(1,-1);
        cout<<ans<<endl;
        return 0;
    }
    



  • 相关阅读:
    Codechef EDGEST 树套树 树状数组 线段树 LCA 卡常
    BZOJ4319 cerc2008 Suffix reconstruction 字符串 SA
    Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal
    Codeforces 316G3 Good Substrings 字符串 SAM
    Codechef CHSIGN Change the Signs(May Challenge 2018) 动态规划
    BZOJ1396 识别子串 字符串 SAM 线段树
    CodeForces 516C Drazil and Park 线段树
    CodeForces 516B Drazil and Tiles 其他
    CodeForces 516A Drazil and Factorial 动态规划
    SPOJ LCS2
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3265355.html
Copyright © 2020-2023  润新知