zoukankan      html  css  js  c++  java
  • 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;
    }
    



  • 相关阅读:
    ble_app_hrs心率程序 nrf51822
    2019.05.08 《Linux驱动开发入门与实战》
    函数指针
    typedef
    回调函数
    android2
    android1
    每周总结2
    HTML
    数组(续)
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3265355.html
Copyright © 2011-2022 走看看