[Codeforces 1294F] Three Paths on a Tree | Tree shape dp, tree diameter

Main idea:

Given a tree with n (3 ≤ n ≤ 2 ⋅ 1 0 5) n\ (3\leq n\leq2\cdot 10^5)n (3n2105 )Unauthorized tree with nodes, try to find three nodesuuuvvv w w w

card ⁡ ({path between u, v} ∪ {path between v, w} ∪ {path between w, u}) \operatorname{card}(\{u,v\text{ path}\} \cup\{path between v,w\text{}\}\cup\{path between w,u\text{}\}) card({ u,path between v } { v ,path between w } { w,The path between u } ) is the  largest.

You need to output two lines:

The first line is MAX card ⁡ ({path between u, v} ∪ {path between v, w} ∪ {path between w, u}) MAX\operatorname{card}(\{u,v\text{ between Path)\}\cup\{v,w\text{ path}\}\cup\{w,u\text{ path}\})MAXcard({ u,path between v } { v ,path between w } { w,The path between u } ) 
Three integers in the second line, namelyuuuvvv w w w , if there are multiple answers, just output one.

Question idea:

The Joker is actually my own series. After I finished writing, I thought it was a correct solution, but I didn't expect it to be a deviation, but it's fine if A is dropped.

Look at the general solutions on the Internet and find the diameter of the tree, because the two points between the three points must be the two end points of the tree diameter, and then find a point that has the largest distance to the tree diameter

Then look at the clown's solution:

First draw a conclusion, if there is one or more degrees ≥ 3 \ge33 node, then the final answer will definitely be handed over at this point. On the contrary, if it is not stated that the tree is a chain (the answer to a chain is obvious)

Based on the answer, the degree is greater than 3 3The conclusion of the point 3 , then you can find three points based on this pointu, ∣ degreeu ≥ 3 ∣ u,|degree_u \ge 3|u ,degreein3 is the end point, then the three longest paths, and record the maximum value of the path and the other end point of the path respectively. Finally, take a sequence and take the top three

How to maintain the endpoints and maximum values ​​of the three paths-tree dp + just change the root

Attach the code of the clown:

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn = 2e6+700;
const ll mod= 1e9+7;
const ll up = 1e13;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
vector<int>v[maxn];
int dp[maxn],suf[maxn],pos[maxn];
int b[maxn];
int in[maxn];
vector< pair<int,int> >g[maxn];
void dfs(int u,int fa){
    
    
	pos[u] = u;
	for(int e:v[u]){
    
    
		if(e == fa) continue;
		dfs(e,u);
		if(dp[u]<dp[e]+1){
    
    
			dp[u] = dp[e]+1;
			pos[u] = pos[e];
		}
	}
}
int a = 0,bt = 0,c = 0;
int maxl = 0;
int res[5];
void work(int u,int fa){
    
    
	if(u!=fa){
    
    

		if(suf[u]<suf[fa]+1) suf[u] = suf[fa]+1,b[u] = b[fa];
		if(g[fa][0].second != pos[u]){
    
    
			if(suf[u] < g[fa][0].first+2) suf[u] = g[fa][0].first+2,b[u] = g[fa][0].second; 
		}
		else if(g[fa].size()>1){
    
    
			if(suf[u] < g[fa][1].first+2) suf[u] = g[fa][1].first+2,b[u] = g[fa][1].second;
		}
	}else b[u] = u;
	for(int e:v[u]){
    
    
		if(e == fa) continue;
		work(e,u);
	}
}
int main(){
    
    
	int mx = 0;
	read(n);
	for(int i=1;i<=n-1;i++){
    
    
		int x,y;read(x);read(y);
		v[x].push_back(y);
		v[y].push_back(x);
		in[y]++;in[x]++;
	}
	for(int i=1;i<=n;i++) mx = max(mx,in[i]);
	if(mx<=2){
    
    
		printf("%lld\n",n-1);
		int last = 1;
		for(int i=1;i<=n;i++)
			if(in[i] == 1){
    
    
				printf("%d ",i);
			}else last = i;
		printf("%d\n",last);
	}else{
    
    
		dfs(1,1);
		for(int i=1;i<=n;i++){
    
    
			for(int x:v[i]){
    
    
				if(dp[x] < dp[i])
					g[i].push_back({
    
    dp[x],pos[x]});	
			}
		}
		for(int i=1;i<=n;i++) sort(g[i].begin(),g[i].end(),greater<pair<int,int>>());
		work(1,1);
		for(int i=1;i<=n;i++){
    
    
			for(auto &x:g[i]) x.first++;
			 g[i].push_back({
    
    suf[i],b[i]});
		}
		for(int i=1;i<=n;i++) sort(g[i].begin(),g[i].end(),greater<pair<int,int>>());
		for(int i=1;i<=n;i++){
    
    
			ll sum = 0;
			if(g[i].size()>=3){
    
    
				for(int k=0;k<3;k++) sum += g[i][k].first;
				if(maxl<sum){
    
    
					maxl = sum;
					for(int k=0;k<3;k++) res[k] = g[i][k].second;
				}
			}
		}
		di(maxl);
		for(int i=0;i<3;i++) printf("%d ",res[i]);
		printf("\n");
	}
	return 0;
}
/***
10
1 2
1 3
2 4
2 5
5 8
5 9
3 6
3 7
7 10
***/

Guess you like

Origin blog.csdn.net/qq_43857314/article/details/112504554