zoukankan      html  css  js  c++  java
  • 树的直径

    树的直径

    定义:树的直径为树中最远的两个节点的距离之和。在求树的直径时一般有两种方法:树形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);
    }
    
  • 相关阅读:
    [JSOI2007][BZOJ1031] 字符加密Cipher|后缀数组
    leetcode Flatten Binary Tree to Linked List
    leetcode Pascal's Triangle
    leetcode Triangle
    leetcode Valid Palindrome
    leetcode Word Ladder
    leetcode Longest Consecutive Sequence
    leetcode Sum Root to Leaf Numbers
    leetcode Clone Graph
    leetcode Evaluate Reverse Polish Notation
  • 原文地址:https://www.cnblogs.com/StungYep/p/12252201.html
Copyright © 2011-2022 走看看