zoukankan      html  css  js  c++  java
  • 测试5T3-星座

    星空中有n颗星星,有n-1对星星间被人为地连上了线,每条连线有各自的长度。所有星星被连成了一个整体。现在,你要在星系中找到一个最大的十字形星座。即,你要找到两条星星构成的路径,使得它们恰好有一颗公共星(这颗公共星不能是某条路径的端点),且两条路径的长度和最大。

    左图红线表示了一个合法的十字形星座,而右图的星座并不合法。

    这里写图片描述

    输入
    第一行一个数n,表示星星的数量。

    接下来n行,每行3个数x,y,z,表示第x颗星星和第y颗星星间有一条连线,它的长度是z。

    输出
    一行,包含一个整数,表示最大的路径长度和。若答案不存在,输出-1。

    样例输入
    10
    3 8 6
    9 3 5
    1 9 2
    4 8 6
    2 3 3
    10 4 8
    5 9 5
    7 2 3
    6 9 1
    样例输出
    33
    提示
    20%的数据n<=1000

    50%的数据n<=10,000

    100%的数据n<=100,000,0<=z<=1000

    这道题讲道理暴力应该有50分,但是打炸了~~

    这里我们用一个f和g数组,任选一个树根,dfs树上DP,f[i][0][1][2][3]分别表示从i开始,向下走到某个叶子为止最长、第二长、第三长、第四长的路径长度。从叶子向树根的顺序DP。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define maxn 100005
    using namespace std;
    int head[maxn],next[maxn*2],ans=0,n,dis[maxn],num=0,val[maxn*2],to[maxn*2],s[maxn][5],b[maxn][5],g[maxn];
    void make_way(int u,int v,int c)
    {
        to[++num]=v;
        next[num]=head[u];
        val[num]=c;
        head[u]=num;
    }
    int dfs(int u,int fa)
    {
        for(int edge=head[u];edge;edge=next[edge])
        if(to[edge]!=fa)
        {
            dis[to[edge]]=dis[u]+val[edge];
            dfs(to[edge],u);
            int p=s[to[edge]][1]+val[edge];
            if(p>s[u][1]){
                s[u][4]=s[u][3];
                b[u][4]=b[u][3];
                s[u][3]=s[u][2];
                b[u][3]=b[u][2];
                s[u][2]=s[u][1];
                b[u][2]=b[u][1];
                s[u][1]=p;
                b[u][1]=to[edge];
            }else
            if(p>s[u][2])
            {
                s[u][4]=s[u][3];
                b[u][4]=b[u][3];
                s[u][3]=s[u][2];
                b[u][3]=b[u][2];
                s[u][2]=p;
                b[u][2]=to[edge];
            }else
            if(p>s[u][3])
            {
                s[u][4]=s[u][3];
                b[u][4]=b[u][3];
                s[u][3]=p;
                b[u][3]=to[edge];
            }else
            if(p>s[u][4])
            s[u][4]=p,b[u][4]=p;
        }
        return dis[u];
    }
    void dp(int u,int fa)
    {
        for(int edge=head[u];edge;edge=next[edge])
        if(to[edge]!=fa)
        {
            if(to[edge]==b[u][1])
            g[to[edge]]=max(s[u][2],g[u])+val[edge];else
            g[to[edge]]=max(s[u][1],g[u])+val[edge]; 
            dp(to[edge],u);
        }
        if(s[u][4])
        ans=max(ans,s[u][4]+s[u][1]+s[u][2]+s[u][3]);
        if(s[u][3])
        ans=max(ans,s[u][1]+s[u][2]+s[u][3]+g[u]);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int u,v,c;
            scanf("%d %d %d",&u,&v,&c);
            make_way(u,v,c);
            make_way(v,u,c);
        }
        dfs(1,0); 
        dp(1,0);
        cout<<ans<<endl;
    }
  • 相关阅读:
    Linux驱动之异常处理体系结构简析
    Linux驱动之按键驱动编写(查询方式)
    Linux驱动之LED驱动编写
    Linux驱动之建立一个hello模块
    Linux驱动之内核加载模块过程分析
    制作根文件系统之制作根文件系统步骤详解
    制作根文件系统之Busybox init进程的启动过程分析
    制作根文件系统之内核如何启动init进程
    制作根文件系统之内核挂接文件系统步骤分析
    Linux移植之tag参数列表解析过程分析
  • 原文地址:https://www.cnblogs.com/dancer16/p/7045538.html
Copyright © 2011-2022 走看看