分析
我们发现一个点是否可以作为魔法书的点
当且仅当距离他最近的点的距离
所以我们可以像求树的直径一样DP
求得每个点向下的距离最大值和距离次大值以及向上的距离最大值
最后在求完之后,统计一下有多少个点满足
即可
时间复杂度:
期望得分:100分
代码
//CF337D #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #define LL long long #define Cl(X,Y) memset((X),(Y),sizeof(X)) #define FOR(i,A,B) for(int i=A;i<=B;i++) #define BOR(i,A,B) for(int i=A;i>=B;i--) #define Lowbit(X) (X & (-X)) #define Skip cout<<endl; #define INF 0x3f3f3f3f #define Mod 998244353 #define Rson (X<<1|1) #define Lson (X<<1) using namespace std; const int MaxN=1e5+10; int Down_one[MaxN],Up[MaxN],Down_two[MaxN],Son[MaxN]; int Total,Side,Limit,Cnt; int u,v,w,Opt,Ans; int Next[MaxN<<1],Head[MaxN],End[MaxN<<1],Cur; bool Jud[MaxN]; inline void File() { freopen(".in","r",stdin); freopen(".out","w",stdout); } inline void DFS_two(int New,int Pre) { int Temp; if(Son[Pre]==New) { Temp=(Jud[Pre] ? max(1,max(Down_two[Pre] ? Down_two[Pre]+1 : 0,Up[Pre] ? Up[Pre]+1 : 0)) : max(Down_two[Pre] ? Down_two[Pre]+1 : 0,Up[Pre] ? Up[Pre]+1 : 0)); } else { Temp=(Jud[Pre] ? max(1,max(Down_one[Pre] ? Down_one[Pre]+1 : 0,Up[Pre] ? Up[Pre]+1 : 0)) : max(Down_one[Pre] ? Down_one[Pre]+1 : 0,Up[Pre] ? Up[Pre]+1 : 0)); } Up[New]=max(Up[New],Temp); if(Down_one[New]<=Limit && Up[New]<=Limit) Ans++; for(int i=Head[New];i;i=Next[i]) { if(End[i]==Pre) continue; DFS_two(End[i],New); } } inline void DFS_one(int New,int Pre) { for(int i=Head[New];i;i=Next[i]) { if(End[i]==Pre) continue; DFS_one(End[i],New); int Temp=(Jud[End[i]] ? max(1,Down_one[End[i]] ? Down_one[End[i]]+1 : 0) : (Down_one[End[i]] ? Down_one[End[i]]+1 : 0)); if(Temp>Down_one[New]) { Down_two[New]=Down_one[New]; Down_one[New]=Temp; Son[New]=End[i]; } else if(Temp>Down_two[New]) { Down_two[New]=Temp; } // FOR(i,1,Total) { cout<<"i: "<<i<<" Down_two: "<<Down_two[i]<<" Down_one: "<<Down_one[i]<<" Up: "<<Up[i]<<endl; } } } inline void Add_Edge(int From,int To) { Next[++Cur]=Head[From]; Head[From]=Cur; End[Cur]=To; } int main() { // File(); ios::sync_with_stdio(false); cin>>Total>>Cnt>>Limit; FOR(i,1,Cnt) { cin>>u; Jud[u]=true; } FOR(i,1,Total-1) { cin>>u>>v; Add_Edge(u,v); Add_Edge(v,u); } DFS_one(1,0); DFS_two(1,0); // FOR(i,1,Total) { cout<<"i: "<<i<<" Down_two: "<<Down_two[i]<<" Down_one: "<<Down_one[i]<<" Up: "<<Up[i]<<endl; } cout<<Ans<<endl; // fclose(stdin); // fclose(stdout); system("pause"); return 0; }