Three Paths on a Tree
题意:在一棵树上找三个不同点,使的三点之间的路径通过最多的不同边。
解法:将树看一条长链像有机化学里的结构式,可以肯定长链的两端点(两次dfs找出最长链)是答案中的两点,第三个点有两种情况:
1、没有支链即只有一条长链第三点即为不同于端点的任意一点。
2、有支链,找一条最长的支链的端点(bfs找最长支链)即可。
//#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF 0x3f3f3f3f
#define mod 20191117
#define PI acos(-1)
#define x first
#define y second
using namespace std;
typedef long long ll ;
vector<int>p;
vector<vector<int>>g;
pair<int , int> dfs(int u , int pre = -1 , int dis = 0)
{
p[u] = pre;
pair<int , int> res = make_pair(dis , u);
for(auto to : g[u])
{
if(pre == to) continue ;
res = max(res , dfs(to , u , dis+1));
}
return res ;
}
int main()
{
int n ;
scanf("%d" , &n);
p = vector<int>(n);
g = vector<vector<int>>(n);
for(int i = 0 ; i < n-1 ; i++)
{
int u , v ;
scanf("%d%d" , &u , &v);
u-- , v-- ;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int>diam;
pair<int , int>db , sb;
db = dfs(0);
sb = dfs(db.y);
int v = sb.y ;
while(v != db.y)
{
diam.push_back(v);
v = p[v];
}
diam.push_back(v);
if(diam.size() == n)
{
cout << n - 1 << " " << endl << diam[0] + 1 << " " << diam[1]+1 << " " << diam.back() + 1 << endl;
}
else{
vector<int>d(n , -1);
queue<int>q;
for(auto &i : diam)
{
q.push(i);
d[i] = 0;
}
while(!q.empty())
{
int v = q.front();
q.pop();
for(auto to : g[v])
{
if(d[to] == -1)
{
d[to] = d[v] + 1;
q.push(to);
}
}
}
pair<int , int> mx = make_pair(d[0] , 0);
for(int v = 1 ; v < n ; v++)
{
mx = max(mx , make_pair(d[v] , v));
}
cout << diam.size() - 1 + mx.x << endl << diam[0]+1 << " " << mx.y + 1 << " " << diam.back() + 1 << endl;
}
return 0;
}

浙公网安备 33010602011771号