• 树的直径


    前言

    那年,CCF把CSP-S办成了植树节...

    为了准备以后的植树节,教练也在机房让大家种树..


    最近一直在接触树上知识,先来讲讲树的直径绝对不是因为只搞懂了这个

    树的直径,即在一棵树中,最远的两个节点之间的距离,也可以指这条路径。下面树的直径都指的是它的距离长度。

    Tree dp或是两次搜索的时间复杂度都是(O(n))不会树形dp所以不写


    思路

    大致思路是这样的,从根节点(任意一个点都可以)P出发,一次搜索找到离这个点距离最远的点Q,再从点Q出发再次搜索,搜到离Q最远的点W,这样两次搜索到的两个节点Q,W就是直径的两个端点。这样的方法代码量略大,但是可以比较方便地(指与Tree dp比较)记录路径。


    证明

    怎么证明这种方法找到的就是树的直径呢?

    这里需要分类讨论。

    1.P在直径上。

    根据树的直径的定义,Q一定也在直径上。而且因为离直径上的点最远,它还是直径的一个端点。

    2.P不在直径上。

    我们用反证法,假设此时PQ不是直径,AB是直径。

    1

    第一种情况,如图,若AB与PQ有交点C,由于P到Q最远,那么PC+CQ>PC+CA,所以CQ>CA,易得CQ+CB>CA+CB,即CQ+CB>AB,与AB是直径矛盾,所以假设不成立。(其中AB,PQ不一定是直线,画成直线是为了方便)

    2

    第二种情况,如图,若AB与PQ没有交点,M为AB上任意一点,N为PQ上任意一点。首先还是NP+NQ>NQ+MN+MB,同时减掉NQ,得NP>MN+MB,易知NP+MN>MB,所以NP+MN+MA>MB+MA,即NP+MN+MA>AB,与AB是直径矛盾,所以这种情况也不成立。

    证毕。


    代码

    (BFS版)

    #include<bits/stdc++.h>
    using namespace std;
    struct node
    {
        int to,w,next;
    } e[100010*2];
    int head[100010],f[100010],n,m,tot;
    bool vis[100010];
    void add_edge(int from,int to,int cost){e[++tot].next=head[from],head[from]=tot,e[tot].to=to,e[tot].w=cost;}
    void bfs(int v)
    {
        queue <int> q;
        while(!q.empty()) q.pop();
        memset(f,0,sizeof(f));
        memset(vis,0,sizeof(vis));
        q.push(v);
        vis[v]=1;
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            for(int i=head[x];i;i=e[i].next)
                if(f[e[i].to]==0&&!vis[e[i].to])
                {
                    f[e[i].to]=f[x]+e[i].w;
                    q.push(e[i].to);
                }
        }
    }
     
    int main()
    {
        int u,v,w;
        scanf("%d%d",&n,&m);
        tot=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
        bfs(1);
        int maxn=0;
        for(int i=1;i<=n;i++)
            if(f[i]>f[maxn])maxn=i;
        bfs(maxn);
        int ans=0;
        for(int i=1;i<=n;i++)
            if(f[i]>ans)ans=f[i];
        printf("%d
    ",ans);
        return 0;
    }
    

    (DFS)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    long long dst[200010],t,dep[200010],son[200010],maxx,head[200010],ff[200010],vis[200010];
    long long s,l,r,ans,n,m,num;
    
    struct node
    {
        int to,nex;
        long long v;
    }e[400010];
    
    void add(int from,int to,long long v)
    {
        e[++num].to=to;
        e[num].v=v;
        e[num].nex=head[from];
        head[from]=num;
    }
    
    void dfs(int x,int fa)
    {
        for(int i=head[x];i;i=e[i].nex)
    	{
            int v=e[i].to;if(v==fa)continue;
    		ff[v]=x;
            dst[v]=dst[x]+e[i].v;
    		dfs(v,x);
        }
    }
    
    
    int main()
    {
        cin>>n;
        for(int i=1;i<n;i++)
        {
            long long u,v,w;
            cin>>u>>v>>w;
            add(u,v,w);
    		add(v,u,w);
        }
        
        dfs(1,0);
        
        for(int i=1;i<=n;i++)
    		if(dst[i]>maxx)maxx=dst[i],s=i,dst[i]=0;
    		
        dfs(s,0);
        
    	maxx=0;
    	
        for(int i=1;i<=n;i++)
    		if(dst[i]>maxx)maxx=dst[i],t=i;
    		
        printf("%lld
    ",maxx);
        
        return 0;
    }
    
  • 相关阅读:
    FileStreamResult 下载或导出文件
    .net core post自带的json序列化转换出错 post参数为null
    .net Core CodeFirst
    获得IP地址
    vue cli 3 以上添加Less支持
    npm淘宝镜像
    会话状态在此上下文中不可用HttpModule中无法访问Session原因
    Chrome谷歌浏览器中js代码Array.sort排序的bug乱序解决办法
    JS匿名函数递归实现阶乘
    JS URL解析
  • 原文地址:https://www.cnblogs.com/moyujiang/p/12077499.html
Copyright © 2020-2023  润新知