题目传送门
题意:
一棵n个点的树,让你在上面找两两不同的三个点。
这三个点之间的简单路径会形成一个边集。使这个边集尽可能大。
输出边集的大小和这三个点。
数据范围: 。
题解:
找出这棵树的直径,直径的两个端点是q和w。
q和w一定是这3个点中的2个。
第3个点是距离直径最远的点。如果找不到直径外的第3个点,那第3个点就在直径上。
感受:
不知道为什么,这么显然没想出来。
刚睡醒脑子晕晕的,很认真地写了一坨shi。
代码:
#include<bits/stdc++.h>
using namespace std ;
const int maxn = 2e5 + 5 ;
int num = 0 , head[maxn] ;
int n ;
struct Edge
{
int v , next ;
} edge[maxn << 1] ;
bool vis[maxn] ;
vector<int> b ;
set<int> s ;
void add_edge(int u , int v)
{
edge[num].v = v ;
edge[num].next = head[u] ;
head[u] = num ++ ;
}
int dep[maxn] , fa[maxn][25] ;
int len , temp , d[maxn] ;
void dfs1(int f , int u , int deep)
{
dep[u] = deep ;
for(int i = 1 ; i <= 20 ; i ++)
{
int nxt = fa[u][i - 1] ;
fa[u][i] = fa[nxt][i - 1] ;
}
for(int i = head[u] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].v ;
if(v == f) continue ;
fa[v][0] = u ;
dfs1(u , v , deep + 1) ;
}
}
int lca(int x , int y)
{
if(dep[x] < dep[y]) swap(x , y) ;
for(int i = 20 ; i >= 0 ; i --)
if(dep[fa[x][i]] >= dep[y])
x = fa[x][i] ;
if(x == y) return x ;
for(int i = 20 ; i >= 0 ; i --)
if(fa[x][i] != fa[y][i])
x = fa[x][i] , y = fa[y][i] ;
return fa[x][0] ;
}
void dfs(int f , int u)
{
for(int i = head[u] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].v ;
if(v == f) continue ;
d[v] = d[u] + 1 ;
if(d[v] > len) len = d[v] , temp = v ;
dfs(u , v) ;
}
}
int find(int x)
{
len = 0 ;
temp = 0 ;
d[x] = 0 ;
dfs(0 , x) ;
return temp ;
}
void dfs2(int f , int u)
{
vis[u] = 1 ;
for(int i = head[u] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].v ;
if(v == f || vis[v]) continue ;
d[v] = d[u] + 1 ;
if(d[v] > len) len = d[v] , temp = v ;
dfs(u , v) ;
}
}
int ewai(int q , int w)
{
for(int i = head[q] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].v ;
if(v != q && v != w) return v ;
}
}
void solve(int q , int w)
{
int tq = q , tw = w ;
int temp1 = q , temp2 = w ;
int lc = lca(q , w) ;
while(q != lc)
{
vis[q] = 1 , d[q] = 0 ;
b.push_back(q) ;
q = fa[q][0] ;
}
while(w != lc)
{
vis[w] = 1 , d[w] = 0 ;
b.push_back(w) ;
w = fa[w][0] ;
}
vis[lc] = 1 , d[lc] = 0 ;
b.push_back(lc) ;
len = 0 , temp = 0 ;
for(auto u : b) dfs2(0 , u) ;
if(temp == 0) temp = ewai(tq , tw) ;
lc = lca(lc , temp) ;
int ttemp = temp ;
while(tq != lc)
{
s.insert(tq) ;
tq = fa[tq][0] ;
}
while(tw != lc)
{
s.insert(tw) ;
tw = fa[tw][0] ;
}
while(temp != lc)
{
s.insert(temp) ;
temp = fa[temp][0] ;
}
s.insert(lc) ;
/*int cnt = 0 ;
for(auto x : s)
if(x >= 1 && x <= n) cnt ++ ;
printf("%d\n" , cnt - 1) ;*/
printf("%d\n" , s.size() - 1) ;
printf("%d %d %d\n" , temp1 , temp2 , ttemp) ;
}
int main()
{
memset(head , -1 , sizeof(head)) ;
scanf("%d" , &n) ;
for(int i = 1 ; i <= n - 1 ; i ++)
{
int u , v ;
scanf("%d%d" , &u , &v) ;
add_edge(u , v) ;
add_edge(v , u) ;
}
int q = find(1) ;
int w = find(q) ;
dfs1(0 , 1 , 1) ;
solve(q , w) ;
return 0 ;
}