hdu 2196 Computer(树形DP,两次dfs)好好看。。。

来源:互联网 发布:淘宝二手市场怎么买卖 编辑:程序博客网 时间:2024/06/05 18:15

1、http://acm.hdu.edu.cn/showproblem.php?pid=2196

2、题目大意:(参考http://blog.csdn.net/shuangde800/article/details/9732825)

给出一棵树,求每一个结点到其他结点的最远权值和,

对于结点u来说,他的最大权值和可能来自两个方向,一个是u作为根节点到其子节点的最大值,另一个是以u的父节点为根的树的最大权值和加上根节点到u的距离

假设存在这么一棵树

         1

     2         3

4   5          6

                     7

1是根节点,23是1的孩子,45是2的孩子,6是3的孩子,7是6的孩子

我们假设要求2的最大距离值,有两种状态,

1、2作为根节点,到其孩子的最大距离值

2、2作为选中的路径的子节点,选中的子树以2的父节点1为根节点的子树,我们可以看到以1为根节点的子树的最大值再加上1-2的距离就是所求,但是前提是选中的1结点为根的最大值的子树中不包含2,假设包含2这个结点,那么最大值就是以2为根的,

adj(v-u)表示v-u之间的距离

dp[v][2]=max(dp[u][2],dp[v][0]+adj(v-u)==dp[u][0]?dp[u][1]:dp[u][0])+adj(v-u)

dp[v][0]表示以v为根节点的子树的最大值

dp[v][1]表示以v为根节点的子树的次大值(第二大)

3、超时代码:

#include<stdio.h>#define N 10005#include<vector>#include<algorithm>using namespace std;int dp[N][3];struct node{    int v;    int w;};vector<node> adj[N];void dfs1(int u){    //printf("*****%d\n",adj[u].size());    int biggest=0,bigger=0;    for(int i=0;i<adj[u].size();i++)    {        int vv=adj[u][i].v;        dfs1(vv);        int tmp=dp[vv][0]+adj[u][i].w;        //printf("***%d %d\n",dp[vv][0],adj[u][i].w);        if(tmp>=biggest)        {            bigger=biggest;            biggest=tmp;        }        else if(tmp>bigger)        {            bigger=tmp;        }    }    dp[u][0]=biggest;    dp[u][1]=bigger;}void dfs2(int u){    for(int i=0;i<adj[u].size();i++)    {        int vv=adj[u][i].v;        dp[vv][2]=max(dp[u][2],dp[u][0]==dp[vv][0]+adj[u][i].w?dp[u][1]:dp[u][0])+adj[u][i].w;        dfs2(vv);    }}int main(){    int n,a,b;    while(scanf("%d",&n)!=EOF)    {        for(int i=2;i<=n;i++)        {            scanf("%d%d",&a,&b);            node tmp;            tmp.v=i;            tmp.w=b;            adj[a].push_back(tmp);        }        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]));    }    return 0;}


 

4、AC代码:

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int N = 1e4 + 5;struct Vertex{    int head;} V[N];struct Edge{    int v,w,next;} E[N];int top;void init(){    memset(V,-1,sizeof(V));    top = 0;}void add_edge(int u,int v,int w){    E[top].v = v;    E[top].w = w;    E[top].next = V[u].head;    V[u].head = top++;}int dp[N][3];void dfs1(int u){    int biggest = 0 , bigger = 0;    for(int i=V[u].head; ~i; i=E[i].next)    {        int v = E[i].v;        dfs1(v);        int tmp = dp[v][0]+E[i].w;        if(biggest <= tmp)        {            bigger = biggest;            biggest = tmp;        }        else if(bigger < tmp)            bigger = tmp;    }    dp[u][0] = biggest;    dp[u][1] = bigger;}void dfs2(int u){    for(int i=V[u].head; ~i; i=E[i].next)    {        int v = E[i].v;        dp[v][2] = max(dp[u][2] , dp[v][0]+E[i].w==dp[u][0] ? dp[u][1] : dp[u][0]) + E[i].w;        dfs2(v);    }}int main(){    int n;    while(~scanf("%d",&n))    {        init();        for(int v=2; v<=n; v++)        {            int u,w;            scanf("%d%d",&u,&w);            add_edge(u,v,w);        }        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]));    }    return 0;}


 

0 0
原创粉丝点击