题意简述
给定一棵树,确定它能分成几个菊花图,从小到大输出菊花图的大小。菊花图的大小定义为顶点个数减一。数据保证菊花图的分法唯一。
解题思路
耐心画一下样例三,不难发现两个菊花图的中心点隔着两个点。因此只需找一个度为 1 1 1 的点 x x x ,它所连接的点 y y y 一定是菊花图的中心点。此时存储一下以 y y y 为中心的菊花图的大小,随后遍历所有和 y y y 间隔为 2 2 2 的点,它们一定是别的菊花图的中心。于是将它们塞入队列中进行下一轮处理即可。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,du[200010],ans[200010],cnt=0,vis[200010];
vector<int> G[200010];
set<int> s[200010];
queue<int> q;
signed main(){
cin>>n;
//读入
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
s[u].insert(v);
s[v].insert(u);
du[u]++,du[v]++;
}
//找度为1的点
int Root=0;
for(int i=1;i<=n;i++){
if(du[i]==1&&vis[i]==0){
Root=i;
vis[i]=1;
break;
}
}
q.push(Root);
//BFS
while(!q.empty()){
Root=q.front();
q.pop();
//找中心点
int Centre=0;
for(int i=0;i<G[Root].size();i++){
if(vis[G[Root][i]]==0){
Centre=G[Root][i];
vis[Centre]=1;
break;
}
}
ans[++cnt]=G[Centre].size();
//找下一个(些)中心点
for(int i=0;i<G[Centre].size();i++){
int O=G[Centre][i];
vis[G[Centre][i]]=1;
for(int j=0;j<G[O].size();j++){
if(vis[G[O][j]]==0){
q.push(G[O][j]);
vis[Root]=1;
}
}
}
}
sort(ans+1,ans+cnt+1);
for(int i=1;i<=cnt;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
return 0;
}