[Baltic2003] Gem

[Baltic2003]Gem

Time Limit: 2 Sec  Memory Limit: 64 MB
Submit: 501  Solved: 320
[Submit][Status][Discuss]

Description

给出一棵树,要求你为树上的结点标上权值,权值可以是任意的正整数 唯一的限制条件是相临的两个结点不能标上相同的权值,要求一种方案,使得整棵树的总价值最小。

Input

先给出一个数字N,代表树上有N个点,N<=10000 下面N-1行,代表两个点相连

Output

最小的总权值

Sample Input

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

Sample Output

14

 

 

    结论题,可以证明用到的整数不超过log种,所以直接暴力树上dp即可。。。。。

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=10005;
int to[maxn*2],ne[maxn*2],hd[maxn],num=0;
int qz[maxn][23],n,hz[maxn][23];

inline void add(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num;}

inline void Merge(int x,int son){
	for(int i=1;i<=20;i++) qz[x][i]+=min(qz[son][i-1],hz[son][i+1]);
}

void dfs(int x,int fa){
	for(int i=1;i<=20;i++) qz[x][i]=i;
	
	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){
		dfs(to[i],x);
		Merge(x,to[i]);
	}
	
	for(int i=20;i;i--) hz[x][i]=min(hz[x][i+1],qz[x][i]);
	for(int i=1;i<=20;i++) qz[x][i]=min(qz[x][i],qz[x][i-1]);
}

int main(){
	memset(qz,0x3f,sizeof(qz));
	memset(hz,0x3f,sizeof(hz));
	
	scanf("%d",&n);
	int uu,vv;
	for(int i=1;i<n;i++) scanf("%d%d",&uu,&vv),add(uu,vv),add(vv,uu);
	
	dfs(1,0);

    printf("%d\n",hz[1][1]);
	
	return 0;
}

 

posted @ 2018-05-30 16:00  蒟蒻JHY  阅读(234)  评论(0编辑  收藏  举报