树形dp

来源:互联网 发布:手机健身软件 编辑:程序博客网 时间:2024/06/04 18:12

HDU 2196
题意:给一颗树,求出每个点到其距离最远的点的距离。
输入是,行的编号的点到第一个值的点的距离是第三个点的值;行的编号是从2开始的;
思路:每一个点距离其他点的最大距离只有可能来自两个方向,1是来自以改点为根的子树上,2是来自其父节点;但是有可能其父节点的第一种情况就是来自这个点(比如u->v,以u为根的子树上的最远距离来自以v节点为根的子树),所以在统计第一种情况是要统计最大值还有次大值,发生上述情况后用次大值就可达到最优解;

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct zp{    int u,v,w,Next;} node[10010];int head[20010],cont;int dp[10010][3];//0以该节点为根节点的最大值     1次大值     2来自父节点的最优解void init(){    memset(head,-1,sizeof(head));    memset(dp,0,sizeof(dp));    cont=0;}void dfs1(int u)//得出dp0和1的值{    int maxn=0,smaxn=0;    for(int i=head[u];i!=-1;i=node[i].Next)    {        int v=node[i].v;        dfs1(v);        smaxn=max(smaxn,dp[v][0]+node[i].w);        if(smaxn>maxn)            swap(smaxn,maxn);    }    dp[u][0]=maxn;    dp[u][1]=smaxn;}void dfs2(int u)//得出dp2的值{    for(int i=head[u];i!=-1;i=node[i].Next)    {        int v=node[i].v;        dp[v][2]=max(dp[u][2],dp[v][0]+node[i].w==dp[u][0]?dp[u][1]:dp[u][0])+node[i].w;//如果dp[v][0]+node[i].w==dp[u][0]则说明发生了上面提到的那种情况        dfs2(v);    }}void add_edge(int a,int b,int w){    node[cont].u=b,node[cont].v=a,node[cont].w=w;    node[cont].Next=head[b];    head[b]=cont++;}int main(){    int n;    while(~scanf("%d",&n))    {        init();        for(int i=2;i<=n;i++)        {            int a,b;            scanf("%d%d",&a,&b);            add_edge(i,a,b);        }        dfs1(1);        dp[1][2]=0;        dfs2(1);        for(int i=1;i<=n;i++)            printf("%d\n",max(dp[i][0],dp[i][2]));    }}
0 0