BZOJ 1468 树分治

Posted on 2016-10-24 20:47  yyjxx2010xyu  阅读(122)  评论(0编辑  收藏  举报

求出子树的重心后求出它每个子节点的距离,排序后就可以统计距离小于等于K的点对的个数了,但是会在同一子树内重复,然后在每个子树里面减去小于等于K的点对个数就可以了。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 const int Maxn=10010;
 7 const int Inf=0x3f3f3f3f;
 8 int n,k,Root,u,v,w,Sum,Size[Maxn],Q[Maxn],F[Maxn],d[Maxn],cnt,head[Maxn],vis[Maxn],Top,Ans;
 9 struct EDGE{int to,next,w;}edge[Maxn<<2];
10 inline int Max(int x,int y) {return x>y?x:y;}
11 inline void Add(int u,int v,int w) {edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt++;}
12 void Get_Root(int u,int fa)
13 {
14     Size[u]=1; F[u]=0;
15     for (int i=head[u];i!=-1;i=edge[i].next)
16     {
17         int v=edge[i].to;
18         if (v==fa || vis[v]) continue;
19         Get_Root(v,u);
20         Size[u]+=Size[v];
21         F[u]=Max(F[u],Size[v]);
22     }
23     F[u]=Max(F[u],Sum-Size[u]);
24     if (F[u]<F[Root]) Root=u;
25 }
26 void Get_Deep(int u,int fa)
27 {
28     Q[++Top]=d[u];
29     for (int i=head[u];i!=-1;i=edge[i].next)
30     {
31         int v=edge[i].to;
32         if (v==fa || vis[v]) continue;
33         d[v]=d[u]+edge[i].w;
34         Get_Deep(v,u);
35     }
36 }
37 int Calc(int u,int value)
38 {
39     d[u]=value; Top=0; Get_Deep(u,0);
40     sort(Q+1,Q+Top+1);
41     int l=1,r=Top,Res=0;
42     while (l<=r)
43     {
44         if (Q[l]+Q[r]<=k)
45             Res+=r-l,l++; else r--;
46     }
47     return Res;
48 }
49 void Work(int u)
50 {
51     Ans+=Calc(u,0);  vis[u]=true;
52     for (int i=head[u];i!=-1;i=edge[i].next)
53     {
54         int v=edge[i].to;
55         if (vis[v]) continue;
56         Ans-=Calc(v,edge[i].w);
57         Sum=Size[v]; Root=0;
58         Get_Root(v,u);
59         Work(Root);
60     }
61 }
62 int main()
63 {
64     while (scanf("%d%d",&n,&k)!=EOF)
65     {
66         if (n==0 && k==0) break;
67         Ans=0; cnt=0; memset(head,-1,sizeof(head));
68         for (int i=1;i<n;i++)
69         {
70             scanf("%d%d%d",&u,&v,&w);
71             Add(u,v,w),Add(v,u,w);
72         }
73         memset(vis,false,sizeof(vis));
74         Sum=n; F[0]=Inf;
75         Get_Root(1,0);
76         Work(Root);
77         printf("%d\n",Ans);
78     }
79     return 0;
80 }
C++