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 }
原文地址:https://www.cnblogs.com/meanttobe/p/12255599.html
时间: 2024-10-11 07:41:18