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

題目鏈接

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 (3≤n≤2⋅1053≤n≤2⋅105) — the number of vertices in the tree.

Next n−1n−1 lines describe the edges of the tree in form ai,biai,bi (1≤ai1≤ai, bi≤nbi≤n, ai≠biai≠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, bb and cc, or aa and cc.

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

If there are several answers, you can print any.

Example

input

Copy

8
1 2
2 3
3 4
4 5
4 6
3 7
3 8

output

Copy

5
1 8 6

Note

The picture corresponding to the first example (and another one correct answer):

If you choose vertices 1,5,61,5,6 then the path between 11 and 55 consists of edges (1,2),(2,3),(3,4),(4,5)(1,2),(2,3),(3,4),(4,5), the path between 11 and 66 consists of edges (1,2),(2,3),(3,4),(4,6)(1,2),(2,3),(3,4),(4,6) and the path between 55 and 66 consists of edges (4,5),(4,6)(4,5),(4,6). The union of these paths is (1,2),(2,3),(3,4),(4,5),(4,6)(1,2),(2,3),(3,4),(4,5),(4,6) so the answer is 55. It can be shown that there is no better answer.

 

題意:

給你一顆無向無權樹,結點個數n<=2e5,讓你選三個點a,b,c

使得在a到b的路徑上或者在a到c的路徑上或者在b到c的路徑上的邊數最大,輸出最大邊數和你選的三個點,多個答案輸出任意一個。

思路:

由於樹中任意兩個點之間的路徑唯一,我們不難發現在答案a,b,c中,一定有兩個點是樹的直徑中的兩個端點(有興趣的可以自己證明一下)。因此我們用dfs求樹的任意一條直徑,並標記所求直徑上的點,最後從標記的點搜未標記的點的最遠距離,加上樹的直徑就是答案。注意a,b,c中不能有相同的點。

不能從未標記的點開始搜到標記的點。否則會影響其他未標記的點到標記點的長度。

複雜度O(n)

也可以用LCA做。有興趣者可以自己查找一下LCA的做法。

代碼:

#include<iostream>
#include<stdio.h>
#include<map>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 4e5+10;
int n,m,maxid,maxn;
vector<int> G[N];
int f[N];int d[N];
int vis[N];int path[N];
int book[N];int du[N];
int ans,ct,nid;
void dfs(int x){
	for(int i=0;i<G[x].size();i++){
		int u=G[x][i];
		if(vis[u]==1) continue;
		vis[u]=1;
		if(d[u]<d[x]+1){
 
			d[u]=d[x]+1;
			if(maxn<d[u]){
				maxid=u;
				maxn=d[u];
			}
			path[u]=x;
		}
		dfs(u);
	}
	return;
}
 
void dfss(int x,int num)
{
    //if(num==2) cout<<"& "<<x<<endl;
    if(ct<num){ct=num;nid=x;}
    for(int i=0;i<G[x].size();i++){
		int u=G[x][i];
		if(book[u]==1) continue;
		book[u]=1;
		dfss(u,num+1);
	}
	return;
}
 
int main(){
	int cnt=1,st,ed,idd;
	scanf("%d",&n);
	{
	    m=n-1;
		int flag=0;
		for(int i=1;i<=n;i++) G[i].clear();
		for(int i=1;i<=n;i++) book[i]=0;
		for(int i=1;i<=m;i++){
			int ta,tb;
			scanf("%d%d",&ta,&tb);
			G[ta].push_back(tb);
			G[tb].push_back(ta);
		}
		for(int i=1;i<=n;i++) vis[i]=0;
		maxn=0;
		maxid=0;
		dfs(1);
		int tem=maxid;
		for(int i=1;i<=n;i++) vis[i]=0;
		for(int i=1;i<=n;i++) path[i]=-1;
		for(int i=1;i<=n;i++) d[i]=0;
		maxid=0;
		maxn=0;
		path[tem]=-1;
		vis[tem]=1;
		dfs(tem);
		st=maxid;
		int idd;
		for(int i=maxid;i!=-1;i=path[i]){
			book[i]=1;
			ed=i;
		}
		for(int i=1;i<=n;i++)
		if(book[i]&&i!=st&&i!=ed) idd=i;
		ct=0,nid=idd;
		ans=maxn;
		for(int i=1;i<=n;i++)
		if(book[i]==1){//注意是從標記的點開始搜未標記的點
		    ct=0;
            dfss(i,0);
			if(ans<maxn+ct)
			{
			    //cout<<"debug: "<<i<<" "<<maxn<<" * "<<ct<<endl;
			    ans=maxn+ct;
			    idd=nid;
			}
		}
		printf("%d\n%d %d %d\n",ans,st,ed,idd);
	}
	return 0;
}

 

發佈了533 篇原創文章 · 獲贊 78 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章