# [bzoj 1468][poj 1741]Tree [点分治]

## Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.

## Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.

## Output

For each test case output the answer on a single line.

Sample Input

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0


Sample Output

8

又一道点分治膜版题我果然是只会做膜版啊还是贴上vector造图的代码吧虽然它RE了用数组膜你邻接表AC我也很迷啊好好好一个小时后的我发现自己一个小时前太sb了居然忘了复原vector G了
  1 #include<cstdio>
2 #include<cstring>
3 #include<iostream>
4 #include<algorithm>
5 #include<vector>
6 using namespace std;
7
9     char ch;
10     int re=0;
11     bool flag=0;
12     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
13     ch=='-'?flag=1:re=ch-'0';
14     while((ch=getchar())>='0'&&ch<='9')  re=re*10+ch-'0';
15     return flag?-re:re;
16 }
17
18 struct edge{
19     int to,w;
20     edge(int to=0,int w=0):
21         to(to),w(w){}
22 };
23 const int maxn=10005;
24 vector<edge> G[maxn];
25 int son[maxn],F[maxn];
26 int d[maxn],deep[maxn];
27 bool vis[maxn];
28 int sum,ans,root;
29 int n,K;
30
31 inline void add_edge(int from,int to,int w){
32     G[from].push_back(edge(to,w));
33     G[to].push_back(edge(from,w));
34 }
35
36 bool init(){
38     if(!n)  return 0;
39     memset(G,0,sizeof G);
40     memset(vis,0,sizeof vis);
42     for(int i=0;i<n-1;i++){
45     }
46     return 1;
47 }
48
49 void getroot(int x,int fa){
50     son[x]=1;
51     F[x]=0;
52     int dd=G[x].size();
53     for(int i=0;i<dd;i++){
54         edge &e=G[x][i];
55         if(e.to!=fa&&!vis[e.to]){
56             getroot(e.to,x);
57             son[x]+=son[e.to];
58             F[x]=max(F[x],son[e.to]);
59         }
60     }
61     F[x]=max(F[x],sum-son[x]);
62     if(F[x]<F[root])  root=x;
63 }
64
65 void getdeep(int x,int fa){
66     deep[++deep[0]]=d[x];
67     int dd=G[x].size();
68     for(int i=0;i<dd;i++){
69         edge &e=G[x][i];
70         if(e.to!=fa&&!vis[e.to]){
71             d[e.to]=d[x]+e.w;
72             getdeep(e.to,x);
73         }
74     }
75 }
76
77 int calc(int x,int now){
78     d[x]=now;
79     deep[0]=0;
80     getdeep(x,0);
81     sort(deep+1,deep+deep[0]+1);
82     int t=0;
83     for(int l=1,r=deep[0];l<r;){
84         if(deep[l]+deep[r]<=K){
85             t+=r-l;
86             l++;
87         }
88         else  r--;
89     }
90     return t;
91 }
92
93 void work(int x){
94     ans+=calc(x,0);
95     vis[x]=1;
96     int dd=G[x].size();
97     for(int i=0;i<dd;i++){
98         edge &e=G[x][i];
99         if(!vis[e.to]){
100             ans-=calc(e.to,e.w);
101             sum=son[e.to];
102             root=0;
103             getroot(e.to,root);
104             work(root);
105         }
106     }
107 }
108
109 void solve(){
110     sum=F[root=0]=n;
111     ans=0;
112     getroot(1,0);
113     work(root);
114     printf("%d\n",ans);
115 }
116
117 int main(){
118     //freopen("temp.in","r",stdin);
119     while(init())
120         solve();
121     return 0;
122 }

posted @ 2017-05-17 14:46  ZYBGMZL  阅读(158)  评论(1编辑  收藏  举报