#树形dp#洛谷 4395 [BOI2003]Gem 气垫车


题目

给出一棵树,要求你为树上的结点标上权值,权值可以是任意的正整数

唯一的限制条件是相邻的两个结点不能标上相同的权值,要求一种方案,使得整棵树的总价值最小。


分析

每个结点的权值最大可能为 \(\log{n}\)

所以直接设 \(dp[x][y]\) 表示点 \(x\) 选择的权值为 \(y\) 时的最小总价值,

维护最大值和次大值就可以做到 \(O(n\log{n})\)


代码

#include 
#include 
using namespace std;
const int N=10011; vectorG[N];
int dp[N][21],n,fi[N],se[N],ans=0x3f3f3f3f;
void dfs(int x,int fa){
	int len=G[x].size();
	dp[x][0]=0x3f3f3f3f;
	for (int i=1;i<=20;++i) dp[x][i]=i;
	for (int i=0;idp[x][i]) se[x]=fi[x],fi[x]=i;
	    else if (dp[x][se[x]]>dp[x][i]) se[x]=i; 
}
int main(){
	ios::sync_with_stdio(0);
	cin>>n;
	for (int i=1;i>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs(1,0);
	for (int i=1;i<=20;++i)
	    if (ans>dp[1][i]) ans=dp[1][i];
	return !printf("%d",ans);
}

相关