zoukankan      html  css  js  c++  java
  • HDU2196-Computer

    原题连接:

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


    思路:

    好了,无敌了,经过昨晚4个钟头+今上午1个小时的奋战,这题终于被我AC了

    收获的确是不小。。呵呵

    一步步的总结吧,题意就是让你求给定树中某一个点到其他任意点的最大权值

    (1)总体的思路。一个点到其他任意点的最大权值只有两种可能性,一个是这个值来自的子树,另一个是这个值来自父结点,因为这个点通往外界的出口就只有这两条了

    (2)首先是求出子树的最大权值,这个只需要用一个dfs+记忆化搜索,这里之所以dfs一个根结点就可以得到所有点的f[i][0]是因为,在遍历所有叶子的过程中,它实际就是路过了所有的结点——只有这样才有可能便利到所有的叶子。

    (3)其次要求每个节点的f[i][1],即通过自己的父节点能够达到的最大权值,那么这个值有两种可能性。就这一块纠结了能有几个小时,如果在一开始就很严密的给总结好,就不会有那么多的麻烦了。一是父节点的其他分支,(注!如果这个分枝不存在,那么这个值就是w)另一个是父节点的父节点,我们在这两个值中选择一个更大的赋给f[i][1]。

    (4)还有一个坑了好久的地方是求某节点到叶子的第二长距离,这个也是要考虑到所有的大小可能性,然后仔细的做好分类

    (5)最后说一下这个题的数据结构,即树的存储方式。用了一个struct里面带着两个变量v和w来存储子树和到达子树的距离,然后用一个root数组来存父节点的位置。

    (6)last but not least,这个题在网上好像所有人都是用的两个dfs的做法,而我自创了一个dfs+bfs的做法,或许5个h就是代价吧。。。


    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <queue>
    #define MAX 10007
    using namespace std;
    
    int n;
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    struct node {
        int v,w;
    };
    vector<node> son[MAX];
    __int64 f[MAX][3];
    __int64 dp[MAX];
    int root[MAX];
    queue<int> q;
    int end[MAX];
    
    __int64 dfs1(int s)
    {
        if(f[s][0] != -1) return f[s][0];
        else {
            int len = son[s].size();
            for(int i = 0;i < len;i++)
            {
                int v = son[s][i].v;
                int w = son[s][i].w;
                int nn = w+dfs1(v);
                if(nn>f[s][0]) {
                    if(f[s][0] == f[s][2]) 
                        f[s][0] = nn;
                    else {
                        f[s][2] = f[s][0];
                        f[s][0] = nn;
                    }
                }
                else if(nn>f[s][2]) 
                    f[s][2] = nn;
            }
            return f[s][0];
        }
    }
    
    void bfs()
    {
        while(!q.empty())
        {
            int s = q.front();
            q.pop();    
            int len = son[s].size();
            for(int i = 0;i < len;i++)
            {
                int v = son[s][i].v;
                int w = son[s][i].w;
                
                if(f[v][0]+w != f[s][0]) 
                    f[v][1] = f[s][0]+w;
                else {
                    if(f[s][2] != -1)
                        f[v][1] = w+f[s][2];
                    else 
                        f[v][1] = w;
                }
                
                f[v][1] = max(f[v][1],f[s][1]+w);
                
                dp[v] = max(f[v][0],f[v][1]);
                q.push(v);
            }
        }
    } 
    
    int main()
    {
        while(cin>>n)
        {
            memset(root,-1,sizeof(root));
            for(int i = 1;i <= n;i++)
                son[i].clear();
            int v,w;
            for(int i = 2;i <= n;i++) 
            {
                    cin>>v>>w;
                //构建树 
                node tmp;
                tmp.v = i;
                tmp.w = w;
                son[v].push_back(tmp);
                root[i] = v;
            }
            memset(f,-1,sizeof(f));
            for(int i = 1;i <= n;i++)
                if(son[i].empty()) 
                    f[i][0] = 0;
            //dfs求所有的点到叶子节点的最长距离 
            dfs1(1);
            //bfs求所有点的f[i][1] 
            memset(dp,-1,sizeof(dp));
            dp[1] = f[1][0];//树根节点已经成为了男人 
            q.push(1);
            bfs();
            
            for(int i = 1;i <= n;i++)
                cout<<dp[i]<<endl; 
        }
        return 0;
    }
  • 相关阅读:
    Java面试题(3)Java new一个对象的过程中发生了什么
    spring boot(九):Spring Boot中Redis的使用
    intellij idea 2018
    springboot(八)自定义Filter、自定义Property
    springboot(六)SpringBoot问题汇总
    Java Web之路(五)JSP
    Java
    instrument(2)
    Instrumentation(1)
    Dubbo中订阅和通知解析
  • 原文地址:https://www.cnblogs.com/immortal-worm/p/5144244.html
Copyright © 2011-2022 走看看