zoukankan      html  css  js  c++  java
  • 【BZOJ1776】[Usaco2010 Hol]cowpol 奶牛政坛 树的直径

    【BZOJ1776】[Usaco2010 Hol]cowpol 奶牛政坛

    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

    题解:如果只有一个政党,那么答案就是树的直径,求法:先找到深度最大的点,再找到距离这个深度最大的点最远的点。

    多个政党类似,先找到每个政党深度最大的点,再拿其他点和它比较即可。

    貌似点分才是最优雅的姿势?

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxn=200010;
    int n,k,mx,cnt,rt;
    int to[maxn],next[maxn],head[maxn],dep[maxn],fa[19][maxn],v[maxn],ans[maxn],md[maxn];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void dfs(int x)
    {
    	md[v[x]]=dep[md[v[x]]]>dep[x]?md[v[x]]:x;
    	for(int i=head[x];i!=-1;i=next[i])	fa[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
    }
    int lca(int a,int b)
    {
    	int i;
    	for(i=mx;i>=0;i--)	if(dep[fa[i][a]]>=dep[b])	a=fa[i][a];
    	if(a==b)	return a;
    	for(i=mx;i>=0;i--)	if(fa[i][a]!=fa[i][b])	a=fa[i][a],b=fa[i][b];
    	return fa[0][a];
    }
    int main()
    {
    	n=rd(),k=rd();
    	int i,a,b;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)
    	{
    		v[i]=rd(),a=rd();
    		if(a)	add(a,i);
    		else	rt=i;
    	}
    	dep[rt]=1,dfs(rt);
    	for(mx=1;(1<<mx)<=n;mx++)	for(i=1;i<=n;i++)	fa[mx][i]=fa[mx-1][fa[mx-1][i]];
    	mx--;
    	for(i=1;i<=n;i++)
    	{
    		a=md[v[i]],b=lca(a,i),ans[v[i]]=max(ans[v[i]],dep[a]+dep[i]-2*dep[b]);
    	}
    	for(i=1;i<=k;i++)	printf("%d
    ",ans[i]);
    	return 0;
    }
  • 相关阅读:
    16. 3Sum Closest
    17. Letter Combinations of a Phone Number
    20. Valid Parentheses
    77. Combinations
    80. Remove Duplicates from Sorted Array II
    82. Remove Duplicates from Sorted List II
    88. Merge Sorted Array
    257. Binary Tree Paths
    225. Implement Stack using Queues
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7434543.html
Copyright © 2011-2022 走看看