题意:在一棵树上找三个不同点,使的三点之间的路径通过最多的不同边。
解法:将树看一条长链像有机化学里的结构式,可以肯定长链的两端点(两次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; }