• 树的直径


    树的直径

    定义:树的直径为树中最远的两个节点的距离之和。在求树的直径时一般有两种方法:树形dp或则两个BFS(DFS也可以)。

    1.树形dp求解树的直径

    思路:由树的直径定义可知:其树形dp的状态转移方程为:

    [D[x]=max(D[y_i]+Edge(x_i,y_i)) ]

    其中D[x]表示从节点x出发走向以x为根的子树,能够到达的最远距离。

    #include<bits/stdc++.h>
    
    using namespace std;
    const int maxn=1e5+10;
    struct node
    {
        int nex,to,val;
    }edge[maxn];
    int head[maxn],dis[maxn],v[maxn],n,s,res=0,tot=0;
    void add(int from,int to,int val)
    {
        edge[++tot].to=to;
        edge[tot].val=val;
        edge[tot].nex=head[from];
        head[from]=tot;
    }
    void dp(int x)
    {
        v[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].nex)
        {
            int y=edge[i].to;
            if(v[y]) continue;
            dp(y);
            res=max(res,dis[x]+dis[y]+edge[i].val);
            dis[x]=max(dis[x],dis[y]+edge[i].val);
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&s);
        memset(head,-1,sizeof(head));
        for(int i=1;i<n;++i)
        {
            int a,b,val;
            scanf("%d%d%d",&a,&b,&val);
            add(a,b,val);
            add(b,a,val);
        }
        dp(s);
        printf("%d
    ",res);
        system("pause");
    }
    

    2.两次BFS求解树的直径

    两次DFS或者BFS也可以求得树的直径,并且更容易的计算出直径上的具体结点。

    3.两次DFS求解树的直径

    如需求具体方案,只需在第二次dfs的时候记录一下即可,show code:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int maxn=1e5+10;
    const int inf=0x3f3f3f3f;
    struct node
    {
        int nex,to,val;
    }edge[maxn];
    int head[maxn],tot=0,n,m,dis[maxn],res;
    bool v[maxn];
    int start,ed;
    inline void add(int from,int to,int val) 
    {
        edge[++tot].to = to;
        edge[tot].val=val;
        edge[tot].nex=head[from];
        head[from]=tot;
    }
    void dfs(int x)
    {
        v[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].nex){
            int y=edge[i].to;
            if(v[y])    continue;
            dis[y]=dis[x]+edge[i].val;
            dfs(y);
        }
    }
    
    int main()
    {
        memset(v,0,sizeof(v));
        memset(head,-1,sizeof(head));
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;++i){
            int a,b,val;
            scanf("%d %d %d",&a,&b,&val);
            add(a,b,val);
            add(b,a,val);
        }
        for(int i=1;i<=n;++i)
            dis[i]=(i==1)?0:inf;
        dfs(1);                     //找到树的一个端点
        res=0;
        for(int i=1;i<=n;++i) 
            if(dis[i]>res&&dis[i]!=inf){
                res=dis[i];        //找到1的一个最远的端点,start确定
                start=i;
            }
        memset(v, 0, sizeof(v));        //注意重新初始化
        for(int i=1;i<=n;++i)
            dis[i]=(i==start)?0:inf;
        dfs(start);
        res=0;                        //找到离端点最远的结点,距离即为直径
        for(int i=1;i<=n;++i) 
            if(dis[i]>res&&dis[i]!=inf){
                res=dis[i];
                ed=i;
            }
        printf("%d
    ",res);
    }
    
  • 相关阅读:
    Base64字符串在传递过程中加号被转成空格
    IIS无法启动,应用程序池自动关闭,应用程序池XXXX将被自动禁用 解决方案之一
    我要写程序我要写程序
    react native项目改名(仅针对android)
    webpack之html-webpack-plugin的使用
    webpack之React开发环境配置
    webpack之webpack-dev-server的使用
    html2canvas截图空白问题
    webpack源码分析——参数初始化
    webpack源码分析——配置调试环境
  • 原文地址:https://www.cnblogs.com/StungYep/p/12252201.html
Copyright © 2020-2023  润新知