码迷,mamicode.com
首页 > 其他好文 > 详细

HDU2196-Computer(树形dp)

时间:2015-11-13 20:55:33      阅读:410      评论:0      收藏:0      [点我收藏+]

标签:

太开心了,终于做出来了。

先上图技术分享卡了半年的题啊~~~~

 

首先一种简单的做法,就是找到直径的两端,分别dfs一下,求出两端到每个点分别的距离取最大值就ok。

/********************************************************
Problem : 2196 ( Computer )     Judge Status : Accepted
RunId : 15495812    Language : G++    Author : G_lory
********************************************************/
#include<bits/stdc++.h>

using namespace std;

const int N = 100005;

vector<int> G[N];
vector<int> L[N];

int dis1[N];
int dis2[N];

int len;
int fa, fb;

void dfs(int pre, int v, int d[], int x)
{
    d[v] = x;
    for (int i = 0; i < G[v].size(); ++i)
    {
        int u = G[v][i];
        if (u == pre) continue;
        dfs(v, u, d, x + L[v][i]);
    }
    if (x > len)
    {
        len = x;
        fa = v;
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    int n;
    int a, b;
    while (cin >> n)
    {
        for (int i = 0; i <= n; ++i)
        {
            G[i].clear();
            L[i].clear();
        }
        for (int i = 2; i <= n; ++i)
        {
            cin >> a >> b;
            G[a].push_back(i);
            G[i].push_back(a);
            L[a].push_back(b);
            L[i].push_back(b);
        }

        len = -1;
        dfs(-1, 1, dis1, 0);
        len = -1;

        dfs(-1, fa, dis1, 0);
        len = -1;
        dfs(-1, fa, dis2, 0);
        for (int i = 1; i <= n; ++i)
        {
            cout << max(dis1[i], dis2[i]) << endl;
        }
    }
    return 0;
}

  

然后是树形dp的做法。真心不懂不懂不懂啊啊啊啊啊!

翻来覆去的看好多大牛小牛的博客,最后终于看kuangbin巨巨的代码明白了。。。心酸。。。看了两三天。。。

 

对于每一个点,它的最长距离一定是它的子树链,或者经过它的父节点的路径。(废话)

第一遍dfs求得是每一个结点子树的最长的次长路径。

第二次dfs是用父节点更新它的每一个子节点。

如果该节点是最长链上的,那么就用次长链更新,否则用最长链更新。

举个栗子。

输入数据:

5

1 1

2 1

3 1

3 1

通过第一遍dfs可以求出

dis[1]=3,sdis[1]=0;

dis[2]=2,sdis[2]=0;

dis[3]=1,sdis[3]=1;

dis[4]=0,sdis[4]=0;

dis[5]=0,sdis[5]=0.

然后第二遍dfs从1开始更新。

2是1的最长子路径,sdis[1]+d[1][2]>sdis[2],sdis[2]=1; 

3是2的最长子路径,sdis[2]+d[2][3]>dis[3],dis[3]=2,sdis[3]=1; 同时更新3的最长子路径为位置为2

dis[3]+d[3][4]>dis[4],dis[4]=3

dis[3]+d[3][5]>dis[5],dis[5]=3

写的啰嗦的,反正就是这么回事 ^_^

/****************************************************
Problem : 2196 ( Computer )     Judge Status : Accepted
RunId : 15496928    Language : G++    Author : G_lory
****************************************************/
#include <bits/stdc++.h>

using namespace std;

const int N = 100005;

vector<int> G[N];
vector<int> L[N];

int dis[N];
int sdis[N];
int id[N];

void dfs(int v, int pre)
{
    for (int i = 0; i < G[v].size(); ++i)
    {
        int u = G[v][i];
        if (u == pre) continue;
        dfs(u, v);
        if (dis[v] < dis[u] + L[v][i])
        {
            sdis[v] = dis[v];
            dis[v] = dis[u] + L[v][i];
            id[v] = u;
        }
        else if (sdis[v] < dis[u] + L[v][i])
        {
            sdis[v] = dis[u] + L[v][i];
        }
    }
}

void dfs1(int v, int pre)
{
    for (unsigned i = 0; i < G[v].size(); ++i)
    {
        int u = G[v][i];
        if (u == pre) continue;
        if (u == id[v])
        {
            if (L[v][i] + sdis[v] > dis[u])
            {
                sdis[u] = dis[u];
                dis[u] = L[v][i] + sdis[v];
                id[u] = v;
            }
            else if (L[v][i] + sdis[v] > sdis[u])
            {
                sdis[u] = L[v][i] + sdis[v];
            }
        }
        else
        {
            if (L[v][i] + dis[v] > dis[u])
            {
                sdis[u] = dis[u];
                dis[u] = L[v][i] + dis[v];
                id[u] = v;
            }
            else if (L[v][i] + dis[v] > sdis[u])
            {
                sdis[u] = L[v][i] + dis[v];
            }
        }
        dfs1(u, v);
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    int n;
    int a, b;
    while (cin >> n)
    {
        memset(dis, 0, sizeof dis);
        memset(sdis, 0, sizeof sdis);
        for (int i = 0; i <= n; ++i)
        {
            G[i].clear();
            L[i].clear();
        }
        for (int i = 2; i <= n; ++i)
        {
            cin >> a >> b;
            G[a].push_back(i);
            G[i].push_back(a);
            L[a].push_back(b);
            L[i].push_back(b);
        }
        dfs(1, -1);
        dfs1(1, -1);
        for (int i = 1; i <= n; ++i)
        {
            cout << dis[i] << endl;
        }
    }
    return 0;
}

  

 

技术分享

HDU2196-Computer(树形dp)

标签:

原文地址:http://www.cnblogs.com/wenruo/p/4963180.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!