[Codeforces 1294F] 나무 위의 세 경로 | 나무 모양 dp, 나무 지름

주요 아이디어 :

n (3 ≤ n ≤ 2 ⋅ 10 5) n \ (3 \ leq n \ leq2 \ cdot 10 ^ 5) 인 나무가 주어집니다.n ( 3 21 05 )노드가있는 인증되지 않은 트리, 3 개의 노드 찾기uuuvvvwww

card ⁡ ({path between u, v} ∪ {path between v, w} ∪ {path between w, u}) \ operatorname {card} (\ {u, v \ text {path} \} \ cup \ {path v, w \ text {} \} \ cup \ {w, u \ text {} \} 사이의 경로) c a r d ( { u ,v } 사이의 경로 { v ,w } 사이의 경로 { w ,u } ) 사이의 경로  가장 큽니다.

두 줄을 출력해야합니다.

첫 번째 줄은 MAX 카드입니다 ⁡ ({path between u, v} ∪ {path between v, w} ∪ {path between w, u}) MAX \ operatorname {card} (\ {u, v \ text {between Path) \} \ cup \ {v, w \ text {경로} \} \ cup \ {w, u \ text {경로} \})M A Xc a r d ( { u ,v } 사이의 경로 { v ,w } 사이의 경로 { w ,u 사이의 경로 } ) 
두 번째 줄에있는 세 개의 정수, 즉uuuvvvwww , 답변이 여러 개인 경우 하나만 출력합니다.

질문 아이디어 :

조커는 사실 저만의 시리즈입니다. 글을 다 쓴 후 올바른 해답이라고 생각했지만 편차가있을 거라고 생각하지 않았지만 A를 떨어 뜨려도 괜찮습니다.

인터넷에서 일반적인 솔루션을보고 나무의 지름을 찾으십시오. 세 점 사이의 두 점이 나무 지름의 두 끝 점이되어야하기 때문입니다. 그런 다음 나무 지름과 가장 거리가 먼 지점을 찾으십시오.

그런 다음 광대의 해결책을 살펴보십시오.

먼저 결론을 내리십시오. 각도가 하나 이상인 경우 ≥ 3 \ ge33 노드이면이 시점에서 최종 답변이 확실히 전달됩니다. 반대로 나무가 사슬이라고 명시되지 않은 경우 (사슬에 대한 답은 분명합니다)

답에 따르면 정도가 3 3 보다 큽니다. 3 의 결론은이 점u, ∣ degreeu ≥ 3 ∣ u, | degree_u \ ge 3 |u ,d e g r e e3 는 끝점, 다음 세 개의 가장 긴 경로, 경로의 최대 값과 경로의 다른 끝점을 각각 기록합니다. 마지막으로 순서를 잡고 상위 3 개

세 경로 트리 dp의 끝점과 최대 값을 유지하는 방법 + 그냥 루트 변경

광대 코드 첨부 :

암호:

/*** 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
***/

추천

출처blog.csdn.net/qq_43857314/article/details/112504554