BZOJ1776: [Usaco2010 Hol]cowpol 奶牛政坛

n<=100000个点的树,每个点属于一个K<=n/2个集合中的一个,每个集合至少两个点,求每个集合中任选两点距离的最大值。

方法一:什么都看不出来,点分,每次只统计经过一个点的每个集合的不同子树的路径来更新。详见http://www.cnblogs.com/Enceladus/p/6099250.html腾爷好强!

方法二:点分过程中我们每次只考虑来自根节点不同子树的最深的两个点来加,但如果所有同集合点都在一棵子树那答案就是最深到次深,也就是说不管怎么选最深都要选,不妨先把每个集合最深的点找出来直接lca找每个集合答案即可。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 int n,K;
 9 #define maxn 400011
10 struct Edge{int to,next;};
11 struct List{int id,next;}list[maxn];int first[maxn],li=2;
12 int most[maxn],bel[maxn];
13 struct Tree
14 {
15     Edge edge[maxn];
16     int first[maxn],le,dis[maxn];
17     Tree()
18     {
19         memset(first,0,sizeof(first));le=2;
20         memset(dis,0,sizeof(dis));
21     }
22     void in(int x,int y)
23     {
24         edge[le].to=y;
25         edge[le].next=first[x];
26         first[x]=le++;
27     }
28     void insert(int x,int y)
29     {
30         in(x,y);
31         in(y,x);
32     }
33     int f[maxn][22];
34     void dfs(int x,int fa)
35     {
36         dis[x]=dis[fa]+1;f[x][0]=fa;
37         if (dis[x]>dis[most[bel[x]]]) most[bel[x]]=x;
38         for (int i=first[x];i;i=edge[i].next)
39         {
40             Edge &e=edge[i];
41             if (e.to!=fa) dfs(e.to,x);
42         }
43     }
44     void dfs() {dis[0]=0;dfs(1,0);}
45     void pre()
46     {
47         for (int j=1;j<=20;j++)
48             for (int i=1;i<=n;i++)
49                 f[i][j]=f[f[i][j-1]][j-1];
50     }
51     int lca(int x,int y)
52     {
53         if (x==y) return x;
54         if (dis[x]<dis[y]) {int t=x;x=y;y=t;}
55         for (int j=20;j!=-1;j--) if (dis[f[x][j]]>=dis[y]) x=f[x][j];
56         if (x==y) return x;
57         for (int j=20;j!=-1;j--) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
58         return f[x][0];
59     }
60 }t;
61 int x;
62 void in(int x,int y)
63 {
64     list[li].id=y;
65     list[li].next=first[x];
66     first[x]=li++;
67 }
68 int main()
69 {
70     scanf("%d%d",&n,&K);
71     for (int i=1;i<=n;i++)
72     {
73         scanf("%d%d",&bel[i],&x);
74         if (x) t.insert(x,i);
75         in(bel[i],i);
76     }
77     memset(most,0,sizeof(most));
78     t.dfs();
79     t.pre();
80     for (int i=1;i<=K;i++)
81     {
82         int ans=0;
83         for (int j=first[i];j;j=list[j].next)
84         {
85             List &e=list[j];
86             ans=max(ans,t.dis[e.id]+t.dis[most[i]]-2*t.dis[t.lca(e.id,most[i])]);
87         }
88         printf("%d\n",ans);
89     }
90     return 0;
91 }
View Code

 

posted @ 2017-08-29 16:01  Blue233333  阅读(209)  评论(0编辑  收藏  举报