zoukankan      html  css  js  c++  java
  • HDU2196-Computer(树形dp)

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

    先上图卡了半年的题啊~~~~

    首先一种简单的做法,就是找到直径的两端,分别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;
    }
    

      

  • 相关阅读:
    IT运维监控解决方案介绍
    Apdex——衡量服务器性能的标准
    服务器监控(包括性能指标与web应用程序)
    使用厂商MIB库查找设备OID值并实施监控的方法
    华为USG6550 MIB CPU MEM
    LInux下实时网络流量监控工具nload教程
    11gR2 集群(CRS/GRID)新功能—— SCAN(Single Client Access Name)
    如何实现网卡bond
    LeetCode(31)-Factorial Trailing Zeroes
    activiti自己定义流程之整合(五):启动流程时获取自己定义表单
  • 原文地址:https://www.cnblogs.com/wenruo/p/4963180.html
Copyright © 2011-2022 走看看