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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM