直径Codeforces 633F木/木DP

質問の意味:ゲームをプレイするには、2人の子供があり、それぞれの子は、出発点と隣接する点と、その選択に選択される次のポイントを選択することができ、最大2回の選挙のポイントを求める権利はどのくらいですか?

アイデア:まず、この問題は2つのツリーに変換することができ、最大値と互いに素の経路を求める権利をドット、この問題のために、我々は2つのアイデアを持っています:

1:木の直径は、受信する前に質問し、より多くのHDUの学校インスピレーションを、私たちはまず、予約セクションの直径を列挙答えを更新するために、予約のこの部分での最適解を見つけるために木の直径を見つけます。

コード:

#include <ビット/ STDC ++ H> 
に#define INF 1E18 
の#define長い長LL 
名前空間stdを使用。
const int型MAXN = 100010; 
ベクター<INT> G [MAXN]。
TOT LL; 
[MAXN] fは、今int型。
LL D [MAXN]、ヴァル[MAXN]和[MAXN]。
BOOL V [MAXN]、V1 [MAXN]。
LL [MAXN] MX。
ボイド追加(int型のx、int型のY){ 
	G [X] .push_back(Y)。
	G [Y] .push_back(X)。
} 
ボイドDFS(int型のx、int型FA、LLの合計){ 
	合計+ = valの[X]。
	V1 [X] = 1。
	F [X] = FA。
	(和> TOT)であれば{ 
		今= X。
		TOT =合計。
	} 
	(自動Y:G [X])が{ 
		IF(Y == FA || V [Y])続けます。
		DFS(Y、X、合計)。
	} 
}
ボイドDFS1(int型のx、int型FA){ 
	D [X] = valの[X]。
	LL TMP = 0。
	(自動Y:G [X])のために、{ 
		(Y == FA || V [Y])が続く場合、
		DFS1(Y、X)。
		TMP = MAX(TMP、D [Y])。
	} 
	D [X] + = TMP。
	返します。
} 
ベクトル<整数>。
INTのmain(){ 
	int型のn、X、Y。
	scanf関数( "%のD"、&N); 
	以下のために(INT i = 1; iが<= N; iが++){ 
		scanf関数( "%のLLD"、およびヴァル[I])。
	} 
	{ため(iは++; iがn <I = 1 INT)
		のscanf( "%d個の%のD"、およびX&Y)を、
		(x、y)を加えます。
	} 
	LL ANS = 0。
	TOT = 0、今= 0; 
	DFS(1、0、0); 
	TOT = 0; 
	DFS(今、0、0); 
	I;;(今= Iをint型のため
		a.push_back(I); 
		和[a.size()] =和[a.size() - 1] +ヴァル[I]。
		V [I] = 1。
	} 
	(自動Y:A)のための{ 
		DFS1(Y、0); 
	} 
	のmemset(V1、0、はsizeof(V1))。
	以下のために(; iがn = <; iは1 = int型私は++){ 
		IF(V [I] == 1つの|| V1 [I] == 1)続けます。
		TOT =今= 0; 
		DFS(I、0、0); 
		TOT = 0; 
		DFS(今、0、0); 
		ANS = MAX(ANS、TOT +和[a.size()])。
	} 
	MX [a.size() - 1] = D [a.size() - 1]。
	ための式(I = a.size()がINT - 2; I> = 1; i--){ 
		MX [i]は] = MAX(MX [[I + 1]、和[a.size() ] -和[I] + D [I]] -ヴァル[[I])。
	} 
	ため(INT i = 0; iは()a.sizeを< - 1; iは++){ 
		ANS = MAX(ANS、D [I] +和[I] + MX [[I + 1]]) ; 
	}
	printf( "%LLDする\ n"、ANS)。
}

2考える:ツリーDPを、我々は各点のリーフノードへの最長経路および二次経路長を保持し、最長パスをルートとそのサブツリーを有します。DPが完了した後、我々は、その後、別の最長経路を見つける行く経路として選択されたノードのサブツリーの各ノードの列挙を尊重します。接頭辞と接尾辞、および親の答えの方向への影響を考慮する必要性への配慮の必要性と最大値を最適化することが可能な最大。

コード:

#include <ビット/ STDC ++ H> 
に#define LL長い長
の#define PLL対<LL、LL> 
名前空間stdを使用。
const int型MAXN = 100010; 
ベクター<INT> G [MAXN]。
LLのmx_path [MAXN]は、[MAXN] mx_dis。
LL lmx_path [MAXN]、[MAXN] rmx_path。
PLL [MAXN] lmx_dis、[MAXN] rmx_dis。
LLヴァル[MAXN]。
LL ANS = 0。
ボイド追加(int型のx、int型のY){ 
	G [X] .push_back(Y)。
	G [Y] .push_back(X)。
} 
ボイドDFS(int型のx、int型FA){ 
	ベクトル<LL> TMP(3)。
	以下のための(自動Y:Gは、[X]){ 
		IF(Y == FA)続けます。
		DFS(Y、X)。
		TMP [0] = mx_dis [Y]。
		ソート(tmp.begin()、tmp.end()); 
		mx_path [X] = MAX(mx_path [Y]、mx_path [X])。
	}
	mx_dis [X] = TMP [2] + valの[X]。
	mx_path [X] = MAX(mx_path [X]、TMP [1] + TMP [2] + valの[X])。
	返します。
} 
int型のTOT、[MAXN]。
構造体ノード{ 
	int型のx、FA。
	mx_p LL、mx_d。
}。
キュー<ノード> Q; 
ボイド解く(){ 
	q.push((ノード){1、0、0、0})。
	一方、(q.size()){ 
		ノードTMP = q.front()。
		q.pop(); 
		TOT = 0; 
		int型のx = tmp.x、FA = tmp.fa。
		TOT = 0; 
		以下のために(INT i = 0; iは、Gを<[X] .size(); iは++){ 
			(G [x]は[I] == FA)続ける場合。
			【++ TOT] = G [X] [I]; 
		} 
		rmx_path [TOT + 1] = rmx_path [TOT + 2] = 0; 
		rmx_dis [TOT + 1] = rmx_dis [TOT + 2] = make_pair(0、0);
		以下のために(; I <= TOT; I = 1 int型私は++){
			}そうであれば(mx_dis [I]]> rmx_dis [I] .second){
			lmx_path [I] = MAX(lmx_path [I - 1]、mx_path [I])。
			lmx_dis [I] = lmx_dis [I - 1]。
			IF(mx_dis [I]]> = lmx_dis [i]が1次回){ 
				lmx_dis [I] .second = lmx_dis [i]が1次回。
				lmx_dis [i]が1次回= mx_dis [I]]。
			}そうであれば(mx_dis [I]]> lmx_dis [I] .second){ 
				lmx_dis [I] .second = mx_dis [I]]。
			} 
		} 
		のためには、(INT iがTOTを=; I> = 1; i--){ 
			rmx_path [I] = MAX(rmx_path [I + 1]、mx_pathを[I])。
			rmx_dis [I] = rmx_dis [I + 1]。
			IF(mx_dis [I]]> = rmx_dis [i]が1次回){ 
				rmx_dis [I] .second = rmx_dis [i]が1次回。
				rmx_dis [i]が1次回= mx_dis [I]]。 
		} 
		LLのTMP1 = 0。
				rmx_dis [I] .second = mx_dis [I]]。
			} 
//のprintf( "%d個の\ n"、X)。
//ため(INT I = 1; I <= TOT; iは++){ 
//のprintf( "%のLLD%のLLDを\ n"、lmx_path [i]は、rmx_path [I])。
//} 
		ため(INT I = 1; I <= TOT; iは++){ 
			LLのTMP2 = 0。
			TMP2 = MAX(TMP2、lmx_path [I - 1])。
			TMP2 = MAX(TMP2、rmx_path [I + 1])。
			TMP2 = MAX(TMP2、tmp.mx_p)。
			TMP2 = MAX(TMP2、ヴァル[X] + lmx_dis [I - 1] + 1次回tmp.mx_d)。
			TMP2 = MAX(TMP2、ヴァル[X] + rmx_dis [I + 1] + 1次回tmp.mx_d)。
			TMP2 = MAX(TMP2、ヴァル[X] + lmx_dis [I - 1] + 1次回lmx_dis [I - 1] .second)。
			TMP2 = MAX(TMP2、ヴァル[X] + rmx_dis [I + 1] + 1次回rmx_dis [I + 1] .second)。
			TMP2 = MAX(TMP2、ヴァル[X] + lmx_dis [I - 1] + 1次回rmx_dis [I + 1] 1次回)。
			TMP2 = MAX(TMP2、ヴァル[X] + tmp.mx_d + MAX(lmx_dis [I - 1] 1次回、[I + 1] 1次回)rmx_dis)。
// printfの( "%のLLD"、tmp.mx_d)。
// printfの( "%のLLD"、TMP2)。
			q.pushは((ノード){[i]は、X、TMP2、ヴァル[X] + MAX(MAX(lmx_dis [I - 1] 1次回、[I + 1] 1次回)、tmp.mx_d)rmx_dis} ); 
			TMP2 + = mx_path [I]]。
// printfの( "%LLDの\ nを"、TMP2)。
			TMP1 = MAX(TMP1、TMP2)。
		} 
//のprintf( "の\ n"); 
		ANS = MAX(ANS、TMP1)。
		ANS = MAX(ANS、tmp.mx_p + mx_path [X])。
	} 
} 
int型のmain(){ 
	int型のn、X、Y。
// freopenは( "633Fin.txt"、 "R"、STDIN)。
// freopenは( "out1.txt"、 "W"、STDOUT)。
	scanf関数( "%のD"、&N);
	{ため(; iがn <I ++はI = 1 INT)
		I ++){ scanf関数( "%d個の%のD"、およびX&Y)。
		(x、y)を加えます。
	}
	DFS(1、0); 
	解決する(); 
	printf( "%LLDする\ n"、ANS)。
}

 

おすすめ

転載: www.cnblogs.com/pkgunboat/p/11427154.html