【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 }