codeforce F - Three Paths on a Tree

Posted pangbi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforce F - Three Paths on a Tree相关的知识,希望对你有一定的参考价值。

F. Three Paths on a Tree
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 edges which belong to at least one of the simple paths between aa and bb, bb and cc, or aa and cc is the maximum possible. See the notes section for a better understanding.

The simple path is the path that visits each vertex at most once.

Input

The first line contains one integer number nn (3n21053≤n≤2⋅105) — the number of vertices in the tree.

Next n1n−1 lines describe the edges of the tree in form ai,biai,bi (1ai1≤ai, binbi≤n, aibiai≠bi). It is guaranteed that given graph is a tree.

Output

In the first line print one integer resres — the maximum number of edges which belong to at least one of the simple paths between aa and bb, bband cc, or aa and cc.

In the second line print three integers a,b,ca,b,c such that 1a,b,cn1≤a,b,c≤n and a,bc,aca≠,b≠c,a≠c.

If there are several answers, you can print any.

 

 

 

DescriptionDescription


给出一棵无权树(可理解为边权为 11 ),你需要选取三个点 a,b,ca,b,c ,最大化 a,ba,b 和 b,cb,c 和 a,ca,c 的简单路径的并集的长度。

 

输出这个最大长度和 a,b,ca,b,c 。

SolutionSolution


有一个结论:

 

必定会有一组最优解,使得 a,ba,b 是树直径上的端点。

这个结论我现在暂时不会证明,大家可以去看看其他 dalaodalao 的证明或是自己给出证明 >v<>v< 。

  

那我们可以套路地去把树直径两端点求出来,这里不推荐用 树形dp ,推荐大家用 两次搜索 求出树直径端点。

确定了 a,ba,b ,接下来我们只要去找到最优的 cc ,就可以最大化答案了。

此时我们注意到:a,ba,b 和 b,cb,c 和 a,ca,c 的简单路径的并集的长度其实就是 dis(a,b)+dis(b,c)+dis(a,c)2dis(a,b)+dis(b,c)+dis(a,c)2 。

此时 dis(a,b)dis(a,b) 已经确定了,当 dis(b,c)+dis(a,c)dis(b,c)+dis(a,c) 的值取到最大,那么整个式子取最大。

把 a,ba,b 到所有点的简单路径距离求出来,去枚举这个最优的 cc 即可,枚举的过程中记得判与 a,ba,b 相同的情况。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=4e5+10;
 4 int head[maxn]; int num=-1;
 5 int dis[maxn];
 6 int tmp1[maxn],tmp2[maxn];
 7 int pos,ans;
 8 struct node
 9 {
10     int v,w;
11     int next;
12 }G[maxn];
13 void add(int u,int v,int w)
14 {
15     G[++num].v=v;G[num].w=w;G[num].next=head[u];head[u]=num;
16     G[++num].v=u;G[num].w=w;G[num].next=head[v];head[v]=num;
17 }
18 void dfs(int u,int fa)
19 {
20     if(dis[u]>ans){
21         ans=dis[u];
22         pos=u;
23     }
24     for(int i=head[u];i!=-1;i=G[i].next){
25         int v=G[i].v;
26         if(v==fa) continue;
27         dis[v]=dis[u]+G[i].w;
28         dfs(v,u);
29     }
30     return;
31 }
32 void init()
33 {
34     memset(head,-1,sizeof(head));
35     num=-1;
36 }
37 int main()
38 {
39     init();
40     int n;
41     scanf("%d",&n);
42     for(int i=1;i<n;i++){
43         int u,v;
44         scanf("%d%d",&u,&v);
45         add(u,v,1);
46     }
47     dfs(1,0);
48     memset(dis,0,sizeof(dis));
49     int p1=pos;
50     ans=0;
51     dfs(pos,0);
52     int p2=pos;
53     for(int i=1;i<=n;i++)
54         tmp1[i]=dis[i];
55     memset(dis,0,sizeof(dis));
56     dfs(pos,0);
57     for(int i=1;i<=n;i++)
58         tmp2[i]=dis[i];
59     pos=0;
60     for(int i=1;i<=n;i++){
61         if(tmp1[i]+tmp2[i]>tmp1[pos]+tmp2[pos]&&i!=p1&&i!=p2)
62             pos=i;
63     }
64     ans=(tmp1[p2]+tmp1[pos]+tmp2[pos])/2;
65     printf("%d
",ans);
66     printf("%d %d %d
",p1,p2,pos);
67     return 0;
68 }

 

以上是关于codeforce F - Three Paths on a Tree的主要内容,如果未能解决你的问题,请参考以下文章

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

CodeForces 1294F Three Paths on a Tree

Codeforces 1006 F - Xor-Paths

Codeforces#498F. Xor-Paths(折半搜索)

题解 CF1294F Three Paths on a Tree

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