YY_More

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一道基础的树形动态规划。就是求从树里每个点出发的最长链的长度。考虑到这个最长链可能是从子节点来的也可能是从父节点来的,我们进行两次DFS。第一次是从儿子到父亲方向,维护从每个节点到儿子节点方向的最长链和次长链。第二次维护从父亲方向来的最长链,有两种情况,如果父亲节点第一次DFS得到的最长链来自正在遍历的子节点,则从父亲的次长链转移,否则直接从父亲的最长链转移。

问题是我的程序怎么那么慢呢。。。简化掉一些memset之后还是100+ms,奇怪。

//By YY_More
#include<cstdio>
#include<cstring>
struct treetype{
	int child;
	int brother;
	int data;
};	
int f[10001][2],g[10001],from[10001],n,v,s;
treetype tree[10001];
void init(){
	for (int i=1;i<=n;i++){
		tree[i].child=0;
		tree[i].brother=0;
	memset(f,0,8*n);
	g[0]=0;
	}	
};
void dp(int x){
	int temp=tree[x].child;
	while (temp!=0){
		dp(temp);
		if (f[temp][0]+tree[temp].data>f[x][0]){
			f[x][1]=f[x][0];
			f[x][0]=f[temp][0]+tree[temp].data;
			from[x]=temp;
		}else
			if (f[temp][0]+tree[temp].data>f[x][1]) f[x][1]=f[temp][0]+tree[temp].data;
		temp=tree[temp].brother;
	}
};	
void dfs(int x){
	int temp=tree[x].child;
	while (temp!=0){
		if (from[x]==temp)
			g[temp]=f[x][1]+tree[temp].data;
		else g[temp]=f[x][0]+tree[temp].data;
		if (g[x]+tree[temp].data>g[temp]) g[temp]=g[x]+tree[temp].data;
		dfs(temp);
		temp=tree[temp].brother;
	}
};	
int main(){
	while (~scanf("%d",&n)){
		init();
		for (int i=2;i<=n;i++){
			scanf("%d%d",&s,&v);
			tree[i].data=v;
			tree[i].brother=tree[s].child;
			tree[s].child=i;
		}
		dp(1);
		dfs(1);
		for (int i=1;i<=n;i++)
			if (f[i][0]>g[i]) printf("%d\n",f[i][0]);
				else printf("%d\n",g[i]);
	}			
	return 0;
}
posted on 2011-07-02 10:14  YY_More  阅读(283)  评论(0编辑  收藏  举报