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;
 }

原文地址:https://www.cnblogs.com/overrate-wsj/p/12231134.html

时间: 2024-11-02 13:49:12

Codeforces1294F. Three Paths on a Tree(两次BFS求树的直径)的相关文章

两次bfs求树的直径的正确性

结论:离树上任意点\(u\)最远的点一定是这颗树直径的一个端点. 证明: 若点\(u\)在树的直径上,设它与直径两个端点\(x,y\)的距离分别为\(S1\).\(S2\),若距离其最远的点\(v\)不是这两个端点, 则\(dist(u,v) > S1 && dist(u,v) > S2\), 则必有\(S1 + dist(u,v) > S1 + S2 或 S2 + dist(u,v) > S1 + S2\),这与\((x,y)\)是直径的 假设相悖. else \

lightoj-1094 Farthest Nodes in a Tree(求树的直径)

1094 - Farthest Nodes in a Tree PDF (English) Statistics ForumTime Limit: 2 second(s) Memory Limit: 32 MBGiven a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. The edges of the tree are weighted and undirect

求树的直径【两遍BFS】

两遍BFS.从任意一个点出发,第一遍可以找到直径的一端,从这端出发即可找到另外一端. 证明:从U点出发,到达V[画个图便清晰了] 1.如果U在直径上,则V一定是直径的一个端点. 2.如果U不在直径上.U,V线一定和直径有交点(如果没有交点,从U引一条路到直径交于U'.[反证]).有交点则V一定是直径另一端. 代码:[举例] int path(int x){ //从x出发,求直径 mem(vis,-1); while(!Q.empty()) Q.pop(); Q.push(x); vis[x]=0

Farthest Nodes in a Tree (求树的直径)

题目链接,密码:hpu Description Given a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. The edges of the tree are weighted and undirected. That means you have to find two nodes in the tree whose distance is maximum a

Problem N HDU 2612 Find a way (两次BFS求最值)

N - Find a way Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2612 Description Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei hav

树的直径| CF#615Div3 F. Three Paths on a Tree

F. Three Paths on a Tree 思路 两种方法: 1.两次bfs求树的直径,顺便求出一个直径端点到所有点的最短距离:再bfs一次,求另一个直径上的端点到其它所有点的最短距离:之后枚举第三个端点(不等于端点1和端点2),dis(a,b) + dis(b,c) + dis(a,c) 再除以 2 就是最终答案,因为每个路径走了两次所以除以2. 2.dfs求树的直径,记录直径上的所有点.从直径上的所有点去搜索它们到不在直径上的点的最远距离.最后直径+这个最远距离就是答案 代码1 bfs

[树的直径]F. Three Paths on a Tree

F. Three Paths on a Tree Description You are given an unweighted tree with nn vertices. Recall that a tree is a connected undirected graph without cycles. Your task is to choose three distinct vertices a,b,ca,b,c on this tree such that the number of

URAL 1145. Rope in the Labyrinth(两次BFS啊 )

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1145 1145. Rope in the Labyrinth Time limit: 0.5 second Memory limit: 64 MB A labyrinth with rectangular form and size m × n is divided into square cells with sides' length 1 by lines that are paralle

树的直径 Codeforces Beta Round #14 (Div. 2) D. Two Paths

tiyi:给你n个节点和n-1条边(无环),求在这个图中找到 两条路径,两路径不相交,求能找的两条路径的长度的乘积最大值: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <queue> #include <stack>