zoukankan      html  css  js  c++  java
  • TyvjP1520 树的直径(模板)

    题目链接

    分析:
    我曾经谈过树的直径
    但是只停留在理论阶段,不会实现
    今天就来填这个史前巨坑

    我在blog提到过:
    设计状态:
    f[i]表示i这棵子树中经过i的最长路径(可以经过i也可以是i作为途中一点)
    g[i]表示i这棵子树中,以i为端点的最长路径

    f[fa]=max(firstmax{w(fa,u)+g[u]},0)+max(secondmax{w(fa,u)+g[u]},0)
    g[fa]=max{w(fa,u)+g[u]}

    然而我发现如果真的按照上述的方程转移的话,就很tomato难受
    我们可以简化一下状态:
    f[i]表示i这棵子树中,以i为端点的最长链
    g[i]表示i这棵子树中,以i为端点的次长链
    这样当前点对答案的贡献就是f[i]+g[i]

    复杂度:O(n)

    这里写图片描述

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=100010;
    int f[N],g[N];
    struct node{
        int x,y,nxt,v;
    };
    node way[N<<1];
    int st[N],tot=0,ans=0,n;
    
    void add(int u,int w,int z)
    {
        tot++;
        way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
    }
    
    void dfs(int now,int fa)
    {
        g[now]=0; f[now]=0;
        for (int i=st[now];i;i=way[i].nxt)
            if (way[i].y!=fa)
            {
                dfs(way[i].y,now);
                int len=way[i].v+f[way[i].y];
                if (len>f[now])
                {
                    g[now]=f[now];
                    f[now]=len;
                }
                else if (len>g[now])
                {
                    g[now]=len;
                }
            }
        ans=max(ans,f[now]+g[now]);
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<n;i++)
        {
            int u,w,z;
            scanf("%d%d%d",&u,&w,&z);
            add(u,w,z);
            add(w,u,z);
        }
        dfs(1,0);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Arrays工具类、二维数组
    Idea软件的使用
    循环语句
    方法
    objective-C 2.0
    Unix系统常用命令
    文献管理工具Zotero
    如何降低论文重复率
    SQL易忽视的细节
    数据库系统原理学习资源
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673139.html
Copyright © 2011-2022 走看看