Codeforces Round #615 (Div. 3) F. Three Paths on a Tree

F. Three Paths on a Tree

原题链接:https://codeforces.com/contest/1294/problem/F

题目大意:

给定一棵树,选出三点,使三点连成的j简单路径最大。简而言之,三个点连成的边的集合大小。

解题思路:

假设任取一点为三点连线的公共点,最长路径就是这个点到其他三个点的三条最长边之和,可知这个点一定在直径上(画图分析假设不在时的最长路径可反证)。所以先求出树的直径,在使用$ans =(a b+a c+b c) / 2$遍历可以得到第三个点。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+10;
 4 vector<int> a[maxn];
 5 int n,vis[maxn],dis1[maxn],dis2[maxn],dis[maxn],pos;
 6 void bfs(int x){
 7     memset(vis,0,sizeof(vis));
 8     memset(dis,0,sizeof(dis));
 9     pos=x;
10     vis[x]=1,dis[x]=0;
11     queue<int> q;
12     q.push(x);
13     while(!q.empty()){
14         int u=q.front();q.pop();
15         for(int i=0;i<a[u].size();i++){
16             if(!vis[a[u][i]]){
17                 vis[a[u][i]]=1;
18                 dis[a[u][i]]=dis[u]+1;
19                 q.push(a[u][i]);
20                 if(dis[a[u][i]]>dis[pos]) pos=a[u][i];
21             }
22         }
23     }
24 }
25 int main(){
26     scanf("%d",&n);
27     int u,v;
28     for(int i=1;i<n;i++){
29         scanf("%d%d",&u,&v);
30         a[u].push_back(v);
31         a[v].push_back(u);
32     }
33        int a,b,c;
34        bfs(1);
35     a=pos;
36     bfs(pos);
37     b=pos;
38        for(int i=1;i<=n;i++){
39         dis1[i]=dis[i];
40     }
41        bfs(pos);
42        for(int i=1;i<=n;i++){
43        dis2[i]=dis[i];
44     }
45        c=0;
46        for(int i=1;i<=n;i++){
47         if(dis1[i]+dis2[i]>dis1[c]+dis2[c]&&i!=a&&i!=b){
48             c=i;
49         }
50     }
51        int ans=(dis1[b]+dis1[c]+dis2[c])/2;
52        cout<<ans<<endl<<a<<" "<<b<<" "<<c;
53     return 0;
54 }

 

posted @ 2020-02-03 14:29  yya雨  阅读(165)  评论(0编辑  收藏  举报