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

    定义:

      给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和。树中最远的两个节点之间的距离被称为树的直径,连接这两点的路径被称为树的最长链。后者通常也可称为直径,即直径是一个 数值概念,也可代指一条路径


    树的直径通常有两种求法,时间复杂度均为O(n)。我们假设树以N个点N-1条边的无向图形式给出,并存储在邻接表中。

    法一:树上DP

    优点:1.代码简单

       2.可以处理出当前点为根时每个子树的最长链。

    缺点:不易求出直径的两个端点。

    法二:两遍DFS(BFS)

    优点:容易计算出直径上的具体节点。

    缺点:只能求直径和距离。

    证明就不再赘述,比较简单,网上也都有。

    打的裸题是POJ 1985 Cow Marathon

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define R register
    #define ll long long
    inline ll read()
    {
    	ll aa=0;char cc=getchar();
    	while(cc<'0'||cc>'9')cc=getchar();
    	while(cc>='0'&&cc<='9')
    		{aa=(aa<<3)+(aa<<1)+(cc^48);cc=getchar();}
    	return aa;
    }
    const int N=1e6;
    int tot,ver[N<<1],nxt[N<<1],edge[N<<1],first[N];
    inline void add(int x,int y,int z)
    {
    	ver[++tot]=y;nxt[tot]=first[x];
    	edge[tot]=z;first[x]=tot;return;
    }
    int n,f[N],ans;
    void dp(int x,int fa)
    {
    	f[x]=0;
    	for(R int i=first[x],v;i;i=nxt[i]){
    		v=ver[i];if(v==fa)continue;
    		dp(v,x);
    		f[0]=max(f[0],f[x]+f[v]+edge[i]);
    		f[x]=max(f[x],f[v]+edge[i]);
    	}
    }
    int dis[N],pi,pj;
    void dfs(int x,int fa)
    {
    	for(R int i=first[x],v;i;i=nxt[i]){
    		v=ver[i];if(v==fa)continue;
    		dis[v]=dis[x]+edge[i];dfs(v,x);
    		if(dis[pj]<dis[v])pj=v;
    	}
    }
    queue<int>qi;
    void bfs(int x)
    {
    	memset(dis,-1,sizeof(dis));dis[x]=0;
    	qi.push(x);
    	while(!qi.empty()){
    		int u=qi.front();qi.pop();
    		for(R int i=first[u],v;i;i=nxt[i]){
    			v=ver[i];if(dis[v]!=-1)continue;
    			dis[v]=dis[u]+edge[i];qi.push(v);
    			if(dis[v]>dis[pj])pj=v;
    		}
    	}
    }
    int main()
    {
    	n=read();read();
    	for(R int i=1,x,y,z;i<n;++i){
    		x=read();y=read();z=read();
    		add(x,y,z);add(y,x,z);
    	}
    	f[0]=0;dp(1,1);ans=f[0];//dp
    	
    	dis[1]=0;pj=1;dfs(1,1);pi=pj;
    	dis[pi]=0;dfs(pi,pi);ans=dis[pj];//dfs
    	
    	pj=1;bfs(1);pi=pj;
    	bfs(pi);ans=dis[pj];//bfs
    	
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    Linux下使用ps命令来查看Oracle相关的进程
    虚继承、虚基类
    C++/C小知识点(2)
    C++中的运行中动态类型识别RTTI
    什么应该放在头文件?何为外连接?
    Placement new、operator new、new operator 完全释疑
    二叉搜索树
    Linux C编程学习资料,学习过程
    独立对象(非附属对象)大小
    编程珠玑第一章、第二章
  • 原文地址:https://www.cnblogs.com/toot-wjh/p/11573183.html
Copyright © 2011-2022 走看看