• 树的直径


    树的直径一般有两种求法,一是两次dfs或bfs,另一种是树形dp

    两次bfs (dfs)

    具体实现上,就是进行两次搜索,第一次的时候以任意的节点为根进行遍历,找到一个距离最远的点,即为直径起点,第二次的时候以该起点为根进行搜索,再找到距离最远的点,即为直径的终点

    注:两次搜索的处理方法可以有效地寻找直径的具体路径,但是无法处理负边权的情况

    //dfs程序
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #define ll long long
    
    inline ll read()
    {
    	ll x=0,f=1;
    	char ch=getchar();
    	while(!isdigit(ch))
    	{
    		if(ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))
    	{
    		x=(x<<1)+(x<<3)+ch-'0';
    		ch=getchar();
    	}
    	return x*f;
    }
    
    const ll maxn=1e4+10;
    const ll inf=1e10+10;
    ll n,ans,maxx=-inf,st,en;
    ll dis[maxn],vis[maxn];
    std::vector<std::pair<ll,ll> > e[maxn];
    
    inline void dfs(ll x)
    {
    	vis[x]=1;
    	for(int i=0;i<e[x].size();i++)
    	{
    		ll y=e[x][i].first;
    		
    		if(!vis[y])
    		{
    			dis[y]=dis[x]+e[x][i].second;
    			
    			dfs(y);
    		}
    	}
    }
    
    int main(void)
    {
    	n=read();
    	for(int i=1;i<=n-1;i++)
    	{
    		ll x=read(),y=read(),z=read();
    		e[x].push_back(std::make_pair(y,z));
    		e[y].push_back(std::make_pair(x,z));
    	}
    	
    	for(int i=1;i<=n;i++) dis[i]=inf;
    	std::memset(vis,0,sizeof(vis));
    	
    	dis[1]=0;
    	dfs(1);
    	
    	for(int i=1;i<=n;i++)
    	{
    		if(dis[i]>maxx&&dis[i]!=inf)
    		{
    			maxx=dis[i];
    			st=i;
    		}
    	}
    	
    	for(int i=1;i<=n;i++) dis[i]=inf;
    	std::memset(vis,0,sizeof(vis));
    	
    	dis[st]=0;
    	dfs(st);
    	
    	maxx=-inf;
    	
    	for(int i=1;i<=n;i++)
    	{
    		if(dis[i]>maxx&&dis[i]!=inf)
    		{
    			maxx=dis[i];
    			en=i;
    		}
    	}
    	
    	printf("%lld
    ",maxx);
    }
    
    //bfs程序
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #define ll long long
    #define db double
    
    const ll maxn=1e4+10;
    const db inf=1e9+10;
    ll n,st,en,tot;
    ll ans,maxx;
    ll dis[maxn],vis[maxn],pre[maxn],used[maxn],head[maxn];
    std::vector<std::pair<ll,ll> > e[maxn];  
    std::queue<ll> q;
    
    struct node
    {
    	ll u,v,w,nxt;
    } s[maxn];
    
    inline void add(ll u,ll v,db w)
    {
    	s[++tot].v=v;
    	s[tot].w=w;
    	s[tot].nxt=head[u];
    	head[u]=tot;
    }
    
    inline void bfs(ll x)
    {
    	pre[x]=0;
    	vis[x]=1;
    	q.push(x);
    	
    	while(q.size())
    	{
    		ll u=q.front();
    		q.pop();
    		
    		for(int i=0;i<e[u].size();i++)
    		{
    			ll v=e[u][i].first;
    			db w=e[u][i].second;
    			
    			if(!vis[v])
    			{
    				pre[v]=u;
    				dis[v]=dis[u]+w;
    				vis[v]=1;
    				q.push(v);
    			}
    		}
    	}
    }
    
    inline void zj()
    {
    	for(int i=1;i<=n;i++) dis[i]=inf;
    	std::memset(vis,0,sizeof(vis));
    	dis[1]=0;	
    	bfs(1);
    	maxx=-1;
    	for(int i=1;i<=n;i++)
    	{
    		if(dis[i]>maxx&&dis[i]!=inf)
    		{
    			st=i;
    			maxx=dis[i];
    		}
    	}
    	for(int i=1;i<=n;i++) dis[i]=inf;
    	memset(vis,0,sizeof(vis));
    	dis[st]=0;
    	bfs(st);
    	maxx=-1;
    	for(int i=1;i<=n;i++)
    	{
    		if(dis[i]>maxx&&dis[i]!=inf)
    		{
    			en=i;
    			maxx=dis[i];
    		}
    	}
    
    	ans+=maxx;
    }
    
    int main(void)
    {
    	scanf("%lld",&n);
    	
    	for(int i=1;i<=n-1;i++)
    	{
    		ll x,y;
    		db z;
    		scanf("%lld %lld %lf",&x,&y,&z);
    		e[x].push_back(std::make_pair(y,z));
    		e[y].push_back(std::make_pair(x,z));
    	}
    	
    	zj();
    
    	printf("%lld
    ",ans);
    	
    	return 0;
    }
    

    DP求解

    一条路径可看为路径中一边与该边两端点到对应直径端点的距离和,在DP中处理最大值,并维护最长链即可

    注:DP可以处理存在负边权的情况,但是不能处理出直径的具体方案

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #define ll long long
    
    inline ll read()
    {
    	ll x=0,f=1;
    	char ch=getchar();
    	while(!isdigit(ch))
    	{
    		if(ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))
    	{
    		x=(x<<1)+(x<<3)+ch-'0';
    		ch=getchar();
    	}
    	return x*f;
    }
    
    const ll maxn=1e5+10;
    ll n,ans=-maxn*maxn,tot;
    ll d[maxn],vis[maxn],head[maxn];
    struct node
    {
    	ll v,w,nxt;
    } s[maxn];
    
    inline void add(ll u,ll v,ll w)
    {
    	s[++tot].v=v;
    	s[tot].w=w;
    	s[tot].nxt=head[u];
    	head[u]=tot;
    }
    
    inline void dp(ll x)
    {
    	vis[x]=1;
    	
    	for(int i=head[x];i;i=s[i].nxt)
    	{
    		ll y=s[i].v;
    		ll w=s[i].w;
    			
    		if(vis[y]) continue;
    		
    		dp(y);
    		
    		ans=std::max(ans,d[x]+d[y]+w);
    		d[x]=std::max(d[x],d[y]+w);
    	}
    }
    
    int main(void)
    {
    	n=read();
    	for(int i=1;i<=n-1;i++)
    	{
    		ll x=read(),y=read(),z=read();
    		add(x,y,z);
    		add(y,x,z);
    	}
    	
    	dp(1);
    	
    	printf("%lld
    ",ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    JVM概论
    设计模式之工厂模式
    Java基础之多线程简述
    设计模式之单例模式
    设计模式之模板方法模式
    设计模式之适配器模式
    设计模式之策略模式
    机器学习浅析之最优解问题(二)
    MapReduce架构与生命周期
    Hadoop系列之实验环境搭建
  • 原文地址:https://www.cnblogs.com/jd1412/p/14066826.html
Copyright © 2020-2023  润新知