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 }