hdu 2196 Computer(树dp)

来源:互联网 发布:电脑网络不通怎么检查 编辑:程序博客网 时间:2024/06/05 07:53

题意:

给出n个点, n-条边,每条边有权值,问从每个点出发能得到的最大值,不返回。


解题思路:

第一道树dp。

树dp的话只不过是转移的关系是在当前节点和几个孩子节点上,也就是从孩子节点转移到当前节点,但由于是一棵树,当前节点的父节点其实也是自己的一个前驱,也可以从父亲节点转移到当前节点,树dp比较麻烦的就是这一步了。


这道题,一个节点出发的最大值的路径无非就是过父亲节点,过孩子节点两种情况。

假设1是根,我们dfs一遍递归处理处每个节点到儿子节点能产生的最大值。

然后再第二遍dfs,将第一遍求得的到儿子节点的最大值和父亲节点出发得到的最大值(这个时候已经求出)比较一下,如果是连接当前节点的边权w+父亲最大值大于当前最大值,那么就更新一下。


然后,有个问题,如果父亲的最大值的情况是过当前节点不就不对了嘛。所以要求出父亲节点不过当前节点的最大值,假如父亲的最大值过了当前节点,那么我们需要一个次大值,而这个值就一定保证了不会过当前节点,就可以转移了。大约树dp比较难的都是这一步??


代码:

#include <bits/stdc++.h>#define ps push_back#define fir first#define sec secondusing namespace std;const int maxn=1e4+5;//vector<pair<int, int> >edg[maxn];struct node{    int to;    int w;    int nex;}edg[maxn*10];int cnt;int head[maxn];void add(int u, int v, int w){    edg[cnt].to=v;    edg[cnt].w=w;    edg[cnt].nex=head[u];    head[u]=cnt++;}int ma[maxn];int mato[maxn];int sma[maxn];int smato[maxn];int n;void dfs1(int x, int fa){    int i, to, w;//    for(i=0; i<(int)edg[x].size(); i++)    for(i=head[x]; i!=-1; i=edg[i].nex)    {//        to=edg[x][i].fir, w=edg[x][i].sec;        to=edg[i].to, w=edg[i].w;        if(to==fa)continue;        dfs1(to, x);//        printf("%d %d %d %d %d\n", x, to, ma[x], ma[to], w);        if(sma[x]<ma[to]+w)        {            sma[x]=ma[to]+w;            smato[x]=to;            if(sma[x]>ma[x])            {                swap(sma[x], ma[x]);                swap(smato[x], mato[x]);            }        }    }    return;}void dfs2(int x, int fa, int w){    if(x!=1)    {        if(mato[fa]!=x)        {    //        printf("%d %d %d %d %d\n", x, fa, w, ma[fa], ma[x]);            if(ma[fa]+w>sma[x])            {                sma[x]=ma[fa]+w;                smato[x]=fa;                if(sma[x]>ma[x])                {                  swap(sma[x], ma[x]);                  swap(mato[x], smato[x]);                }            }                    }        else         {    //        printf("*%d %d %d %d %d\n", x, fa, w, sma[fa], ma[x]);            if(sma[fa]+w>sma[x])            {                sma[x]=sma[fa]+w;                smato[x]=fa;                if(sma[x]>ma[x])                {                    swap(sma[x], ma[x]);                    swap(mato[x], smato[x]);                }            }        }    }    int to, ww;//    for(int i=0; i<(int)edg[x].size(); i++)    for(int i=head[x]; i!=-1; i=edg[i].nex)    {        to=edg[i].to, ww=edg[i].w;        if(to==fa)continue;        dfs2(to, x, ww);    }    return;}int main(){    while(~scanf("%d", &n))    {        cnt=0;        for(int i=0; i<=n; i++)        {            ma[i]=mato[i]=sma[i]=0;            head[i]=-1;        }        int x, y;        pair<int, int>pa;        for(int i=2; i<=n; i++)        {            scanf("%d%d", &x, &y);            //pa.second=y, pa.fir=i;            add(x, i, y);            //edg[x].ps(pa);        }        dfs1(1, 0);        dfs2(1, 0, 0);        for(int i=1; i<=n; i++)printf("%d\n", ma[i]);    }}


原创粉丝点击