Study notes: the center of the tree

Given a tree, the tree contains n nodes (numbered 1~n) and n-1 undirected edges.
Please find the center of gravity of the tree, and output the maximum number of points in the remaining connected blocks after the center of gravity is deleted.

Definition of center of gravity: center of gravity refers to a node in the tree. If the maximum number of points in the remaining connected blocks is the smallest after this point is deleted, then this node is called the center of gravity of the tree.

Input format The
first line contains the integer n, which represents the number of nodes in the tree.
Next n-1 lines, each line contains two integers a and b, indicating that there is an edge between point a and point b.

Output format
Output an integer m, which represents the maximum number of points in each remaining connected block after the center of gravity is deleted.

Idea: Enumerate the situation after each point is deleted, calculate the number of points in the interconnection block, after deleting a point in the tree, the condition of the interconnection block: each subtree of point u is a interconnection block, except for the rest Outside point u and its subtree is another interconnection block

#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#define ll long long
#define ull unsigned long long
#define up_b upper_bound
#define low_b lower_bound
#define m_p make_pair
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#define endl "\n"
#include<algorithm>
using namespace std;

inline ll read()
{
    
    
	ll x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9')	{
    
     if(ch=='-') f=-1; ch=getchar(); }
	while('0'<=ch&&ch<='9')	x=x*10+ch-'0', ch=getchar();
	return f*x;
}

const int N = 1e5+5;

int n;
bool vis[N];
struct node{
    
    int v,next;}edge[2*N];
int head[N],idx;

void add(int u,int v)
{
    
    
	edge[idx]=(node){
    
    v,head[u]};
	head[u]=idx++;
}

int ans=inf;

int dfs(int u) //dfs的返回值是以点u为为根节点的子树的大小
{
    
    
	vis[u]=true; //标记该点被访问
	
	int sum=1,res=0;
	//sum存以点u为为根节点的子树的大小,首先将自己算上,sum=1
	//res存删除点u后,所以联通块中的最大值
	
	for(int i=head[u];~i;i=edge[i].next)
	{
    
    
		int v=edge[i].v;
		if(vis[v])	continue;
		int t=dfs(v);
		res=max(res,t); //在其子树形成的联通块中取一个最大值
		sum+=t;
	}
	res=max(res,n-sum); //除了点u及其子树外的另一个联通块
	ans=min(res,ans); //最终答案在所有res中取一个最小值
	return sum;
}

int main()
{
    
    
	memset(head,-1,sizeof(head));
	
	cin>>n;
	for(int i=1;i<n;i++)
	{
    
    
		int u=read(),v=read();
		add(u,v); add(v,u); //树是无向图,建立双向边
	}
	dfs(1); //遍历整个树,从那个点开始都可以
	cout<<ans<<endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/m0_50815157/article/details/113725567