• 【CF337D】邪恶古籍-树状dp


    Problem 邪恶古籍

    题目大意

    给出一些关键点,求这棵树上到最远关键点距离小于等于d的有多少个。

    Solution

    一个非常简单的树形dp。然而我被这道题给玩坏了。

    在经过分析以后,我们发现只需要维护两个数组,

    一个数组记录这个点的上面的最远关键点(父亲那一串)到这个点的距离;

    另一个数组记录这个点的子树上的最远关键点到这个点的距离。

    这个应该是正解,其实也和我的做法差不多,但是较好理解。

    我的垃圾做法如下:

    对于每一个节点,开三个值,path,pathp,pathn。

    path表示其子树上最远关键点到这个点的距离,

    pathp表示其子树上次远关键点到这个点的距离,且与最远关键点不在同一颗子树上。

    pathn表示其最远关键点所在的子树。

    首先第一次dfs可以求出来这三个值。

    然后再一次dfs,这次dfs的时候,path就变成了全树上最远关键点到这个点的距离,也就是我们最终要求的答案。

    从根节点开始扫,若父亲的pathn指的不是这个点,那么这个点的path值就变成了父亲的path值+1;

    如果父亲的pathn指的就是这个点,那么我们的pathp就起了作用。若pathp的值小于这个点的path值,那么就更新path值。

    当然在这个dfs的过程中,也要保证维护pathp的存在。

    然后为了写这玩意儿我拉低了整题的AC率,所以强烈不推荐这个奇奇怪怪的方法。

    而且我还不知道是不是正解,鬼知道cf的数据强不强。所以如果有错误的话请各位指出。

    反正oj上我是A掉了。

    那么,最后祝各位写题愉快。

    反正这题我写的是很无语的。

    AC Code

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 struct node{
     6     int next,to;
     7 }e[200010];
     8 bool neko[100010];
     9 int n,m,d,x,u,v,path[100010],h[100010],ans=0,tot=0;
    10 int pathp[100010],pathn[100010];
    11 void add(int u,int v){
    12     e[++tot].to=u;e[tot].next=h[v];h[v]=tot;
    13     e[++tot].to=v;e[tot].next=h[u];h[u]=tot;
    14 }
    15 void dfspath(int x,int last){
    16     path[x]=-2333333;pathp[x]=-2333333;
    17     for(int i=h[x];~i;i=e[i].next){
    18         if(e[i].to!=last){
    19             dfspath(e[i].to,x);
    20             if(path[x]<path[e[i].to]+1){
    21                 pathp[x]=path[x];
    22                 path[x]=path[e[i].to]+1;
    23                 pathn[x]=e[i].to;
    24             }else if(pathp[x]<path[e[i].to]+1)pathp[x]=path[e[i].to]+1;
    25         }
    26     }
    27     if(neko[x]&&path[x]<-2000000)path[x]=0;
    28     if(neko[x]&&pathp[x]<-2000000)pathp[x]=0;
    29 }
    30 void dpdfs(int x,int last){
    31     if(~last)
    32     if(pathn[last]==x){
    33         if(pathp[last]+1>path[x]){
    34             pathp[x]=path[x];
    35             path[x]=pathp[last]+1;
    36             pathn[x]=0;
    37         }else if(pathp[last]+1>pathp[x])pathp[x]=pathp[last]+1;
    38     }else{
    39         if(path[last]+1>path[x]){
    40             pathp[x]=path[x];
    41             path[x]=path[last]+1;
    42             pathn[x]=0;
    43         }else if(path[last]+1>pathp[x])
    44             pathp[x]=path[last]+1;
    45     }
    46     if(path[x]<=d)ans++;
    47     for(int i=h[x];~i;i=e[i].next) 
    48         if(e[i].to!=last)dpdfs(e[i].to,x);
    49 }
    50 int main(){
    51 //  freopen("cf337d.in","r",stdin);
    52     memset(h,-1,sizeof(h));
    53     scanf("%d%d%d",&n,&m,&d);
    54     for(int i=1;i<=m;i++)
    55         scanf("%d",&x),neko[x]=1;
    56     for(int i=1;i<n;i++){
    57         scanf("%d%d",&u,&v);
    58         add(u,v);
    59     }
    60     dfspath(1,1);
    61     dpdfs(1,-1);
    62     printf("%d",ans);
    63 }
  • 相关阅读:
    求欧拉回路 UOJ117
    POJ2749 Building road
    POJ3678 Katu Puzzle
    快速修改和上传网站图片技巧
    phpstudy易犯的错误
    关于网站端口的认识
    金融互助后台验证码显示不出来。
    全局搜索数据库
    MySQL命令行导出数据库
    MySQL导入大sql 文件大小限制问题的解决
  • 原文地址:https://www.cnblogs.com/skylynf/p/7141820.html
Copyright © 2020-2023  润新知