[Baltic2003]Gem
Time Limit: 2 Sec Memory Limit: 64 MBSubmit: 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
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;
}