请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
题目连接:https://www.acwing.com/problem/content/description/848/
这个题目有2种解法
解法一:用vector比较易懂和理解。
用vector来存下每个节点的子节点,然后依次进行遍历。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int vis[maxn];
vector<int> p[maxn];
int ans=maxn,n;
int dfs(int u)
{
vis[u]=1;
int sum=1,num=0;
for(int i=0; i<p[u].size(); i++)
{
int j=p[u][i];
if(vis[j])
continue;
int s=dfs(j);
num=max(num,s);
sum+=s;
}
num=max(num,n-sum);
ans=min(num,ans);
return sum;
}
void solve()
{
cin>>n;
int a,b;
for(int i=0; i<n; ++i)
{
cin>>a>>b;
p[a].push_back(b);
p[b].push_back(a);
}
dfs(1);
cout<<ans<<endl;
}
int main()
{
solve();
return 0;
}
解法2:这种解法相当于用了3个数组解决了vector的实现,但是这3个数组比较难懂。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int vis[maxn];
//h数组指的是他的字节点中最右边的那个节点的在所有子节点中的编号
//ne数组指的是当前节点的左边的姐妹节点在所有子节点中的编号
//e数组就是从小到大为每个子节点进行编号
int h[maxn],e[2*maxn],ne[2*maxn];
int idx,ans=maxn,n;
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int dfs(int u)
{
vis[u]=1;
int sum=1,num=0;
for(int i=h[u]; i!=-1; i=ne[i])
{
int j=e[i];
if(vis[j])
continue;
int s=dfs(j);
num=max(num,s);
sum+=s;
}
num=max(num,n-sum);
ans=min(num,ans);
return sum;
}
void solve()
{
cin>>n;
memset(h,-1,sizeof(h));
int a,b;
for(int i=0; i<n; ++i)
{
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs(1);
cout<<ans<<endl;
}
int main()
{
solve();
return 0;
}