并查集判断连通,再每个节点出发DFS记录最大深度,最后输出最大深度。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
#define MAX 10001
bool visit[MAX]={false};
int N;
int Tree[MAX];//保存根节点编号
vector<int> ma[MAX]; //邻接表
int deepth[MAX];//保存从每个点出发所能达到得最大深度
int DFS(int s){//DFS表示以s为起点所能达到得最大深度
int ans=0;
if(visit[s])
return 0;
visit[s]=true;
for(int i=0;i<ma[s].size();i++){
if(!visit[ma[s][i]]){
int tmp=DFS(ma[s][i]);
ans=ans>tmp?ans:tmp;
}
}
return ans+1;
}
void init(int n){ //并查集得初始化
for(int i=1;i<=n;i++)
Tree[i]=-1;
}
int findRoot(int x){//查找x的父节点,并路径压缩
if(Tree[x]==-1)
return x;
else{
int tmp=findRoot(Tree[x]);
Tree[x]=tmp;
return tmp;
}
}
void union_Tree(int x,int y){//合并并查集
x=findRoot(x);
y=findRoot(y);
if(x!=y)
Tree[x]=y;
}
int main(){
scanf("%d",&N);
init(N);
for(int i=1;i<N;i++){
int s,e;
scanf("%d %d",&s,&e);
union_Tree(s,e);
ma[s].push_back(e);
ma[e].push_back(s);
}
int num=0;
for(int i=1;i<=N;i++){
if(Tree[i]==-1)
num++;
}
if(num>1){
printf("Error: %d components\n",num);
return 0;
}
else{
for(int i=1;i<=N;i++){
memset(visit,0,sizeof(visit));
deepth[i]=DFS(i);
}
int max_deep=-1;
for(int i=1;i<=N;i++)
if(deepth[i]>max_deep){
max_deep=deepth[i];
}
for(int i=1;i<=N;i++){
if(deepth[i]==max_deep)
printf("%d\n",i);
}
}
return 0;
}
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
int un[10005];
vector<bool> vis(10005);
vector<vector<int> > mp(10005);
int getfa(int a){
return un[a] = (un[a] == a) ? a : getfa(un[a]);
}
void unin(int a, int b){
un[getfa(a)] = un[getfa(b)];
}
int high(int id){
int h = 0;
vis[id] = true;
for (int i = 0; i < mp[id].size(); ++i){
if (!vis[mp[id][i]]){
vis[mp[id][i]] = true;
h = max(h, high(mp[id][i]));
}
}
return h + 1;
}
int main()
{
int n, a, b;
scanf("%d", &n);
for (int i = 1; i <= n; ++i){
un[i] = i;
}
for (int i = 1; i < n; ++i){
scanf("%d%d", &a, &b);
mp[a].push_back(b);
mp[b].push_back(a);
unin(a, b);
}
set<int> st;
for (int i = 1; i <= n; ++i){
st.insert(getfa(i));
}
if (st.size() == 1){
vector<int> v;
int mn = -1;
for (int i = 1; i <= n; ++i){
vis.assign(n+1, false);
int h = high(i);
if (h > mn){
v.clear();
mn = h;
v.push_back(i);
}else if (h == mn){
v.push_back(i);
}
}
for (int i = 0; i < v.size(); ++i){
printf("%d\n", v[i]);
}
}else{
printf("Error: %d components\n", st.size());
}
return 0;
}
正解应该是用树的直径来做,首先选取一点,找到距离该点最远的点,再从最远点出发找全部最远点,这就是树的直径可证明。
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long LL;
const int INF = 0x7FFFFFFF;
const int maxn = 2e4 + 10;
vector<int> t[maxn];
int n, fa[maxn], x, y, cnt, ans[maxn], dis[maxn], maxd;
int get(int x)
{
return x == fa[x] ? x : fa[x] = get(fa[x]);
}
void dfs(int x, int y, int dep)
{
dis[x] = dep; maxd = max(maxd, dep);
for (int i = 0; i < t[x].size(); i++)
{
if (t[x][i] == y) continue;
dfs(t[x][i], x, dep + 1);
}
}
int main()
{
scanf("%d", &n); cnt = n;
for (int i = 1; i <= n; i++) fa[i] = i;
for (int i = 1; i < n; i++)
{
scanf("%d%d", &x, &y);
int fx = get(x), fy = get(y);
if (fx != fy) { fa[fx] = fy; cnt--; }
t[x].push_back(y); t[y].push_back(x);
}
if (cnt > 1) printf("Error: %d components\n", cnt);
else
{
cnt = 0;
dfs(1, 1, 0);
for (int i = 1; i <= n; i++) if (dis[i] == maxd) ans[cnt++] = i;
for (int i = 1; i <= n; i++) dis[i] = 0;
dfs(ans[0], ans[0], 0);
for (int i = 1; i <= n; i++) if (dis[i] == maxd) ans[cnt++] = i;
sort(ans, ans + cnt);
cnt = unique(ans, ans + cnt) - ans;
for (int i = 0; i < cnt; i++) printf("%d\n", ans[i]);
}
return 0;
}