1. 程式人生 > >CF161D Distance in Tree 點分治

CF161D Distance in Tree 點分治

isp using amp close its max open 樹形 esp

題目:

  輸入點數為N一棵樹,求樹上長度恰好為K的路徑個數

分析:

  題目的數據範圍不是很緊,點分治也可以過,樹形dp也可以過。這裏采用點分治做法。

  我們只需要單開一個類似於桶的數組,跑點分治套路,統計即可,每次處理一棵子樹,先在桶上跑統計,處理完一棵子樹再更新桶。這樣可以保證每一段路徑都直接跨過根節點內。

  記得開long long。

代碼:

技術分享圖片
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=100005,M=505;
 5 struct node{int
y,nxt;}e[N*2]; 6 int d[N],rt,vis[N],siz[N],c=1,q[N]; 7 int h[N],n,m,k,mx[N],sm;ll t[M],ans=0; 8 void add(int x,int y){ 9 e[++c]=(node){y,h[x]};h[x]=c; 10 } void getrt(int x,int fa){ 11 siz[x]=1;mx[x]=0; 12 for(int i=h[x],y;i;i=e[i].nxt) 13 if((y=e[i].y)!=fa&&!vis[y]) 14 getrt(y,x),siz[x]+=siz[y],
15 mx[x]=max(mx[x],siz[y]); 16 mx[x]=max(mx[x],sm-siz[x]); 17 if(mx[x]<mx[rt]) rt=x;return ; 18 } void dfs(int x,int fa){ 19 q[++q[0]]=d[x]; 20 for(int i=h[x],y;i;i=e[i].nxt) 21 if((y=e[i].y)!=fa&&!vis[y]) 22 d[y]=d[x]+1,dfs(y,x);return ; 23 } void calc(int x){ 24
for(int i=h[x],y;i;i=e[i].nxt) 25 if(!vis[y=e[i].y]){ 26 q[0]=0;d[y]=1;dfs(y,x); 27 for(int j=q[0];j;j--) 28 if(q[j]<=k) ans+=t[k-q[j]]; 29 for(int j=q[0];j;j--) 30 if(q[j]<=k) t[q[j]]++; 31 } memset(t,0,sizeof(t)); 32 } void solve(int x){ 33 vis[x]=1;t[0]=1;calc(x); 34 for(int i=h[x],y;i;i=e[i].nxt) 35 if(!vis[y=e[i].y]){ 36 sm=siz[y];mx[rt=0]=N; 37 getrt(y,0);solve(rt); 38 } return ; 39 } int main(){ 40 scanf("%d%d",&n,&k); 41 for(int i=1,x,y;i<n;i++) 42 scanf("%d%d",&x,&y),add(x,y),add(y,x); 43 mx[rt]=sm=n;getrt(1,0);solve(rt); 44 printf("%lld\n",ans);return 0; 45 }
點分治

CF161D Distance in Tree 點分治