[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 ",hz[1][1]); return 0; }