首页 > 代码库 > 倍增LCA BZOJ1776 cowpol奶牛政坛

倍增LCA BZOJ1776 cowpol奶牛政坛

1776: [Usaco2010 Hol]cowpol 奶牛政坛

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 491  Solved: 240
[Submit][Status][Discuss]

Description

农夫约翰的奶牛住在N (2 <= N <= 200,000)片不同的草地上,标号为1到N。恰好有N-1条单位长度的双向道路,用各种各样的方法连接这些草地。而且从每片草地出发都可以抵达其他所有草地。也就是说,这些草地和道路构成了一种叫做树的图。输入包含一个详细的草地的集合,详细说明了每个草地的父节点P_i (0 <= P_i <= N)。根节点的P_i == 0, 表示它没有父节点。因为奶牛建立了1到K一共K (1 <= K <= N/2)个政党。每只奶牛都要加入某一个政党,其中, 第i只奶牛属于第A_i (1 <= A_i <= K)个政党。而且每个政党至少有两只奶牛。 这些政党互相吵闹争。每个政党都想知道自己的“范围”有多大。其中,定义一个政党的范围是这个政党离得最远的两只奶牛(沿着双向道路行走)的距离。 比如说,记为政党1包含奶牛1,3和6,政党2包含奶牛2,4和5。这些草地的连接方式如下图所 示(政党1由-n-表示): 技术分享 政党1最大的两只奶牛的距离是3(也就是奶牛3和奶牛6的距离)。政党2最大的两只奶牛的距离是2(也就是奶牛2和4,4和5,还有5和2之间的距离)。 帮助奶牛们求出每个政党的范围。

Input

* 第一行: 两个由空格隔开的整数: N 和 K * 第2到第N+1行: 第i+1行包含两个由空格隔开的整数: A_i和P_i

Output

* 第1到第K行: 第i行包含一个单独的整数,表示第i个政党的范围。

Sample Input

6 2
1 3
2 1
1 0
2 1
2 1
1 5

Sample Output

3
2

HINT

 

Source

Gold

 
 
这个题其实比较简单,然而我还是不会......我菜得扣脚
需要知道这样的一个事情,路径最长的两端点其中必定有一点是该党派中deep[i]最深的那个点,这个应该是显然......
然而我刚看题的时候天真地认为两段点应该是deep[i]最深的两个点......
当然这个题可以用一个n*n的暴力枚举,不过显然是要TLE。
突然觉得vector真是好用,此题中会非常方便地查找一党派中deep[i]最大的那个点
我废话真多,多半是我太渣,唉......
这个题,用手写的read竟然比scanf慢,震惊!
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 int n,k,root,ans,mxdeep,mx;
 8 int father[200010],group[200010],deep[200010],fa[200010][32];
 9 vector<int>child[200010],party[200010];
10 void dfs(int u){
11     fa[u][0]=father[u];
12     deep[u]=deep[father[u]]+1;
13     for(int i=1;(1<<i)<=n;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
14     for(int i=0;i<child[u].size();i++) dfs(child[u][i]);
15 }
16 int lca(int u,int v){
17     if(deep[u]<deep[v]) swap(u,v);
18     int i=0;
19     for(i=0;(1<<i)<=n;i++);
20     i--;
21     for(int j=i;j>=0;j--)
22         if(deep[u]-(1<<j)>=deep[v]) u=fa[u][j];
23     if(u==v) return u;
24     for(int j=i;j>=0;j--)
25         if(fa[u][j]!=fa[v][j]){
26             u=fa[u][j];
27             v=fa[v][j];
28         }
29     return father[u];
30 }
31 int main(){
32     scanf("%d%d",&n,&k);
33     for(int i=1;i<=n;i++){
34         scanf("%d%d",&group[i],&father[i]);
35         child[father[i]].push_back(i);
36         party[group[i]].push_back(i);
37         if(!father[i]) root=i;
38     }
39     dfs(root);
40     for(int i=1;i<=k;i++){
41         ans=0;
42         mxdeep=0;
43         mx=0;
44         for(int j=0;j<party[i].size();j++)
45             if(deep[party[i][j]]>mxdeep){
46                 mxdeep=deep[party[i][j]];
47                 mx=party[i][j];
48             }
49         for(int j=0;j<party[i].size();j++)
50             ans=max(ans,deep[mx]+deep[party[i][j]]-2*deep[lca(mx,party[i][j])]);
51         printf("%d\n",ans);        
52     }
53     return 0;
54 }

 

倍增LCA BZOJ1776 cowpol奶牛政坛