CF685B Kay and Snowflake

CF685B Kay and Snowflake

题意:输入一棵树,判断每一棵子树的重心是哪一个节点.

题解:
首先关于重心:一棵树将某个点去掉,会把这棵树分为好几块,以最大的一块的结点个数作为 m a x s i z e maxsize maxsize,这样的话每一个点都对应着一个 m a x s i z e maxsize maxsize,这些值当中最小的那个所对应的结点即为树的重心。

定义: G s o n [ i ] Gson[i] Gson[i]表示以 i i i为根的子树中 s i z e size size最大的子树
性质:
1.若 x x x为根节点,这颗子树的重心一定在根节点 x x x上或者是 从 x x x到以Gson[x]的重心的路径上。
2.一个树的重心的 d e p dep dep一定小于等于它的子树的重心。
3.如果一个 G s o n [ x ] Gson[x] Gson[x] s i z e size size 2 2 2大于 x x x s i z e size size,那么重心一定在 G s o n [ x ] Gson[x] Gson[x]的子树里。

//***************树的重心
#include
#define mp make_pair
#define se second
#define fi first
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;

const int N=2e4+10;
const int maxn=300010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=998244353;
int n,m,x,y,z,k,cnt,t,len,q;

vector<int>G[maxn];
int son[maxn];//然后设son[i]表示以i为根的子树的节点个数(不包括根)
int Gson[maxn];//重儿子
//int ans,balance;//ans重心 balance平衡最大子树的最小节点
int ans[maxn];//储存质心的节点
int fa[maxn];

void ReadTree()
{//输入n-1条边
	for(int i=2;i<=n;i++)
	{
		int s,e;
		scanf("%d",&fa[i]);
		e=i;
		G[fa[i]].push_back(e);
		G[e].push_back(fa[i]);
	}
}
void dfs(int u,int fat)
{//O(n)搜一遍即可
	son[u]=1;
	int d=G[u].size();
	int pre_balance=0;
	for(int i=0;i<d;i++)
	{
		int v=G[u][i];
		if(v!=fat)
		{
			dfs(v,u);
			son[u]+=son[v];//合并子树
			int k=v;
			//更新重儿子
			if(son[k]>son[Gson[u]]) Gson[u]=k;
		}
	}
	int k;
	if(son[Gson[u]]*2>son[u]){//如果这个儿子的结点数超过整个的两倍
        k=ans[Gson[u]];
        //应用结论根节点的质心的dep小于子树的质心
        //找到第一个没超过两倍的子树根节点
        //不断向上跳
        while((son[u]-son[k])*2>son[u])k=fa[k];
        ans[u]=k;//以它的节点为质心
    }
    else{
        ans[u]=u;
    }
    return ;

}

    //scanf("%lld%lld",&n,&m);
	//printf("%lld\n",ans);
	//for(int i=1;i<=n;i++)
int main()
{
    scanf("%d%d",&n,&m);
	ReadTree();
	memset(son,0,sizeof(son));
//	ans=0;balance=INF;
	dfs(1,-1);
	for(int i=1;i<=m;i++){
        int x;
       scanf("%d",&x);
       printf("%d\n",ans[x]);
    }
	return 0;
}

你可能感兴趣的:(Codeforces,线段树算法)