【紀中2020.2.7日】模擬賽第四題【樹的重心】

Description

“尼伯龍根是一棵由n-1條高架路連起n 個地區的樹,每一次Load,你都會重生在某一個地區。如果重生點是整個尼伯龍根的重心,也就是這個樹的重心,那麼你就能在最短時間內帶諾諾逃脫啦。”
“對了,再給你一點方便咯,你可以選一條高架橋斷掉,再連接另外兩個地方,每次Load只能用一次技能,而又必須使整個它仍構成樹形結構。你的Save點在這裏,Load自然會恢復原始的尼伯龍根咯。”

輸入

第一行兩個整數n,m,n意義如題,m表示路明非Load了m次。
接下來n-1行,每行兩個整數x,y表示節點x,y之間存在一條邊。
接下來m行,每行一個整數p,表示這次Load的重生地區。

輸出

對於每一個詢問,輸出一行
如果可以則輸出”YES”,否則輸出”NO”(注意沒有引號)

樣例輸入

5 3
1 2
1 3
1 4
1 5
1
2
3

樣例輸出

YES
NO
NO

說明:

我把一篇之前打的Pascal代碼硬生生改成了c++代碼……
還過了??

分析:

找到樹的重心,詢問x個點,去掉任意一條邊,又連上任意兩點,求出它能否成爲樹的重心
就可以找出重心的最大和次大子樹,如果i在最大子樹上,就將次大子樹連上x,不然就將最大子樹連上x,再判斷這個點是否符合重心。

C++ CODE:

#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
int jl[400000],s[400000],g[400000],a[400000],f[400000],x[400000],y[400000];
int n,m,dian,i,p,ji,maxx,max2,jis,ans;
int h[400000][100];
bool bz[400000],zhi[400000],bo;
void dg(int k)
{
	int i,p;
	if(k==12) k=k;
	for(i=1;i<=g[k];i++)
	{
		p=h[k][i];
		if(bz[p]==false)
		{
			bz[p]=true;
			dg(p);
			f[k]=f[k]+f[p];
		}
	}
	f[k]++;
} 
void dg2(int k)
{
	int i,p,t,s;
	s=n-f[k];
	if(bo)
	return;
	s--;
	for(i=1;i<=g[k];i++)
	{
		p=h[k][i];
		if(bz[p])
		continue;
		if(s<f[p])
		s=f[p];
	}
	if(s<=n/2)
	{
		bo=true;
		dian=k;
		return;
	}else
	{
		for(i=1;i<=g[k];i++)
		{
			if(bz[h[k][i]])
			continue;
			bz[h[k][i]]=true;
			dg2(h[k][i]);
			if(bo)
			return;
		}
	}
}
void jilu(int k)
{
	int i,p;
	zhi[k]=true;
	for(i=1;i<=g[k];i++)
	{
		p=h[k][i];
		if(bz[p]==false)
		{
			bz[p]=true;
			jilu(p);
		}
	}
}
int main(){
	freopen("h3.in","r",stdin);
	freopen("h3.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(i=1;i<n;i++)
	{
		scanf("%d%d",&x[i],&y[i]);
		g[x[i]]++;
		h[x[i]][g[x[i]]]=y[i];
		g[y[i]]++;
		h[y[i]][g[y[i]]]=x[i];
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&a[i]);
	}
	memset(bz,false,sizeof(bz));
	memset(f,0,sizeof(f));
	bz[x[1]]=true;
	dg(x[1]);
	memset(bz,false,sizeof(bz));
	bo=false;
	bz[x[i]]=true;
	dg2(x[1]);
	memset(f,0,sizeof(f));
	memset(bz,false,sizeof(bz));
	bz[dian]=true;
	dg(dian);
	for(i=1;i<=g[dian];i++)
	{
		p=h[dian][i];
		if(maxx<f[p])
		{
			maxx=f[p];
			ji=p;
			jis=i;
		}
	}
	memset(bz,false,sizeof(bz));
	memset(zhi,false,sizeof(zhi));
	bz[dian]=true;
	bz[ji]=true;
	ans=1;
	jilu(ji);
	for(i=1;i<=g[dian];i++)
		if(i!=jis)
		{
			p=h[dian][i];
			if(max2<f[p])
			max2=f[p];
		}
	for(i=1;i<=m;i++)
	{
		if(a[i]==dian)
		{
			cout<<"YES"<<endl;
			continue;
		}if(zhi[a[i]])
		{
			if(n-f[a[i]]-max2<=n/2)
			cout<<"YES"<<endl;
			else
			cout<<"NO"<<endl;
		}
		else{
			if(n-f[a[i]]-maxx<=n/2)
			cout<<"YES"<<endl;
			else
			cout<<"NO"<<endl;
		}
	}
	
return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章