Codeforces1294F-Three Paths on a Tree(兩次BFS求樹的直徑)


題意:

給一棵樹,找到三個頂點,使三個頂點兩兩之間路徑的並集最大

思路:

 

必定會有一組最優解,使得 a,b是樹直徑上的端點。

 

證明:

 

假設某個答案取連接點x。x最遠的樹到達的點是s,根據樹的直徑算法,s是樹的某個直徑a的端點。假設x的最遠和第二遠的點組成的鏈是b,b就會和a有一段公共部分。我們取a和b相交部分距離s最遠的那個點y。那么取這個鏈上點y的答案一定比x更優  

 

用兩次BFS可以求出直徑的兩個端點,在這個過程中還能順便求出一個端點到樹上每一點的距離。之后再用一次BFS求得另一個端點到樹上每一點的距離。

 

再枚舉第三個頂點c就可以求出這三個頂點了

 

最終距離為:[dis(a,b)+dis(b,c)+dis(a,c)]/2

兩次BFS求樹的直徑與端點:

那么問題來了,怎么求樹的直徑的呢?這里提供一種兩次BFS求樹的直徑的方法:

 先任選一個起點BFS找到最長路的終點,再從終點進行BFS,則第二次BFS找到的最長路即為樹的直徑;
 原理: 設起點為u,第一次BFS找到的終點v一定是樹的直徑的一個端點
 證明: 1) 如果u 是直徑上的點,則v顯然是直徑的終點(因為如果v不是的話,則必定存在另一個點w使得u到w的距離更長,則於BFS找到了v矛盾)
     2) 如果u不是直徑上的點,則u到v必然於樹的直徑相交(反證),那么交點到v 必然就是直徑的后半段了
 所以v一定是直徑的一個端點,所以從v進行BFS得到的一定是直徑長度

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
 using namespace std;
 const int maxn=2e5+10;
 vector<int> a[maxn];
 int n,vis[maxn],dis1[maxn],dis2[maxn],dis[maxn],pos;
 void bfs(int x)
 {
     memset(vis,0,sizeof(vis));
     memset(dis,0,sizeof(dis));
     pos=x;
     vis[x]=1,dis[x]=0;
     queue<int> q;
     q.push(x);
     while(!q.empty()){
         int u=q.front();q.pop();
         for(int i=0;i<a[u].size();i++){
             if(!vis[a[u][i]]){
                 vis[a[u][i]]=1;
                 dis[a[u][i]]=dis[u]+1;
                 q.push(a[u][i]);
                 if(dis[a[u][i]]>dis[pos]) pos=a[u][i];
             }
         }
     }
 }
 int main()
 {
     scanf("%d",&n);
     int u,v;
     for(int i=1;i<n;i++){
         scanf("%d%d",&u,&v);
         a[u].push_back(v);
         a[v].push_back(u);
     }
    int a,b,c;
    bfs(1),a=pos;
    bfs(pos),b=pos;
    for(int i=1;i<=n;i++)    dis1[i]=dis[i];
    bfs(pos);
    for(int i=1;i<=n;i++)    dis2[i]=dis[i];
    c=0;
    for(int i=1;i<=n;i++)
        if(dis1[i]+dis2[i]>dis1[c]+dis2[c]&&i!=a&&i!=b)    c=i;
    int ans=(dis1[b]+dis1[c]+dis2[c])/2;
    cout<<ans<<endl<<a<<" "<<b<<" "<<c;
     return 0;
 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM