思路一
本题通过暴力法,即对每个节点进行一次dfs可以得到绝大多数的分数。
思路二
参考柳神思路,通过set结构体存储结果,先dfs任意一个节点,将得到的set结构体赋值给ans,然后再从ans里选取任意一节点进行dfs,最后将两次dfs求出来的结果求并集即可得到结果。
尚未理解柳神思路的核心,因此下附求最深根贪心证明原文
下附自己代码:
#include<bits/stdc++.h>
#define N 10111
using namespace std;
int n,anss=1,err=0;
int a[N][N],vis[N],maxx=0;
set<int>b,ans;
void dfs(int x,int deep){
vis[x]=1;
for(int i=1;i<=n;i++)
if(vis[i]!=1&&a[x][i]==1)
{
dfs(i,deep+1);
}
if(deep>maxx){
b.clear();
maxx=deep;
b.insert(x);
}
else if(maxx==deep)
b.insert(x);
}
int main() {
cin>>n;
int t1,t2;
for(int i=1;i<n;i++){
cin>>t1>>t2;
a[t1][t2]=1;
a[t2][t1]=1;
}
//邻接矩阵存储图
dfs(1,0);
ans=b;
//第一次遍历完后ans存储b
memset(vis,0,N);//每次dfs前初始化vis访问矩阵
for(int j = 1; j <= n; j++){
if(vis[j] == 0){
err += 1;
dfs(j, 0);
}
}
if(err > 1){ //判断连通分量数目
printf("Error: %d components", err);
return 0;
}
memset(vis,0,N);
maxx=0;
b.clear();
//第二次用dfs求b的时候需要初始化访问矩阵、最深深度、清空b
dfs(*ans.begin(),0);
for(auto it = b.begin(); it != b.end(); it++){// it != depth.end()
ans.insert(*it); //两个集合求并集(由于是set 直接插入即可)
}
for(auto it = ans.begin(); it != ans.end(); it++){
printf("%d\n", *it);
}
return 0;
}