一道基础的树形动态规划。就是求从树里每个点出发的最长链的长度。考虑到这个最长链可能是从子节点来的也可能是从父节点来的,我们进行两次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;
}
浙公网安备 33010602011771号