思路一
- 用layer[]存储叶节点的最大高度,同时叶节点只会是vector大小为1的节点。
- 判断是不是树只需要判断非连通图的个数即可,可以用并查集和vis[]数组的方法。
思路二
- 任意节点距离最远的点一定是deepest root的集合(证明见算法笔记)
- 从任意一个点遍历得到根集合temp1,从根集合temp1选出一个点遍历的集合temp2,两者的并集即为所求。
注意
- 如果图是无环图,不需要使用vis[]来进行dfs,只需在遍历到前节点时跳过即可。
- n等于1时,输出1。
- 可以使用set,会使题目更加简单。
代码一
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=10001;
int n,maxk=0;
vector<int> adj[maxn];
bool vis[maxn]={false};
int layer[maxn];
void BFS(int u,int dep){
if(dep>layer[u]) layer[u]=dep; //求每个结点的最高高度
if(dep>maxk) maxk=dep; //找出最高高度
vis[u]=true;
for(int i=0;i<adj[u].size();i++){
int v=adj[u][i];
if(vis[v]==false){
BFS(v,dep+1);
}
}
}
void initial(){
for(int i=1;i<=n;i++){
vis[i]=false;
}
}
int BFSTrave(){ //判断是不是树
int ans=0;
for(int i=1;i<=n;i++){
if(vis[i]==false){
BFS(i,0);
ans++;
}
}
return ans;
}
void BFSTrave2(){ //判断每个叶子结点的最大高度
for(int i=1;i<=n;i++){
initial();
if(adj[i].size()==1){
BFS(i,0);
}
}
}
int main(){
scanf("%d",&n);
int a,b;
for(int i=0;i<n-1;i++){
scanf("%d%d",&a,&b);
adj[a].push_back(b);
adj[b].push_back(a);
}
int num=BFSTrave();
if(num==1){
BFSTrave2();
for(int i=1;i<=n;i++){
if(layer[i]==maxk) printf("%d\n",i);
}
}
else {
printf("Error: %d components",num);
}
return 0;
}
代码二
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10010;
vector<int> adj[maxn];
int n,maxk=0;
int father[maxn];
bool isroot[maxn];
int findFather(int x){
int a=x;
while(x!=father[x]){
x=father[x];
}
while(a!=father[a]){
int z=a;
a=father[a];
father[z]=x;
}
return x;
}
void Union(int a,int b){
int fa=findFather(a);
int fb=findFather(b);
if(fa!=fb){
father[fa]=fb;
}
}
void initial(){
for(int i=1;i<=n;i++){
father[i]=i;
}
}
int calblock(){
int ans=0;
for(int i=1;i<=n;i++){
isroot[findFather(i)]=true;
}
for(int i=1;i<=n;i++){
ans+=isroot[i];
}
return ans;
}
set<int> temp,ans;
void DFS(int u,int dep,int pre){
if(dep>maxk){
temp.clear();
temp.insert(u);
maxk=dep;
}
if(dep==maxk){
temp.insert(u);
}
for(int i=0;i<adj[u].size();i++){
if(adj[u][i]==pre) continue; //只能用在无环树
DFS(adj[u][i],dep+1,u);
}
}
int main(){
int a,b;
scanf("%d",&n);
initial();
for(int i=0;i<n-1;i++){
scanf("%d%d",&a,&b);
adj[a].push_back(b);
adj[b].push_back(a);
Union(a,b);
}
int num=calblock();
if(num!=1) printf("Error: %d components",num);
else{
DFS(1,1,-1);
ans=temp;
set<int>::iterator it=ans.begin();
maxk=0;
DFS(*it,1,-1);
for(;it!=ans.end();it++){
temp.insert(*it);
}
int pre=-1;
for(set<int>::iterator it=temp.begin();it!=temp.end();it++){
if(*it!=pre) printf("%d\n",*it);
pre=*it;
}
}
return 0;
}