• 【洛谷P4408】逃学的小孩【树的直径】


    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P4408
    给出一棵树,已知有人一开始在CC点,要到达AA点和BB点(那个近先去哪)。求最坏的情况所需的时间。


    思路:

    转化题意:
    max(dis[A][B]+min(dis[C][A],dis[C][B]))求max(dis[A][B]+min(dis[C][A],dis[C][B]))
    那么为了使答案最大,那么肯定先满足dis[A][B]dis[A][B]尽量大,那么肯定就是求树的直径。那么假设求出的树的直径的两个端点是ppqq,那么很明显可以暴力求出每个点到pp和到qq的较小值,然后取个maxmax即可。
    时间复杂度:O(n)O(n)


    代码:

    //dfs1和dfs2是求直径的两个端点p和q以及直径长度
    //dfs3和dfs4是求每个点到p的距离和到q的距离
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int N=200100;
    int n,m,x,y,z,tot,p,q,head[N];
    ll ans,sum,dis[N];
    
    struct edge
    {
    	int next,to,dis;
    }e[N*2];
    
    void add(int from,int to,int dis)
    {
    	e[++tot].to=to;
    	e[tot].dis=dis;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    void dfs1(int x,int fa,ll s)
    {
    	if (s>sum) sum=s,p=x;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int y=e[i].to;
    		if (y==fa) continue;
    		dfs1(y,x,s+e[i].dis);
    	}
    }
    
    void dfs2(int x,int fa,ll s)
    {
    	if (s>ans) ans=s,q=x;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int y=e[i].to;
    		if (y==fa) continue;
    		dfs2(y,x,s+e[i].dis);
    	}
    }
    
    void dfs3(int x,int fa,ll s)
    {
    	dis[x]=s;
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int y=e[i].to;
    		if (y==fa) continue;
    		dfs3(y,x,s+e[i].dis);
    	}
    }
    
    void dfs4(int x,int fa,ll s)
    {
    	dis[x]=min(dis[x],s);  //在到p的距离和到q的距离中选择更近的那一个
    	for (int i=head[x];~i;i=e[i].next)
    	{
    		int y=e[i].to;
    		if (y==fa) continue;
    		dfs4(y,x,s+e[i].dis);
    	}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z);
    		add(y,x,z);
    	}
    	dfs1(1,0,0);
    	dfs2(p,0,0);
    	dfs3(p,0,0);
    	dfs4(q,0,0);
    	sum=0;
    	for (int i=1;i<=n;i++)
    		sum=max(sum,dis[i]);  //求最大值
    	printf("%lld
    ",sum+ans);  //直径+最大值
    	return 0;
    }
    
  • 相关阅读:
    SCILAB简介[z]
    UG OPEN API编程基础 2约定及编程初步
    Office 2003与Office 2010不能共存的解决方案
    UG OPEN API 编程基础 3用户界面接口
    NewtonRaphson method
    UG OPEN API编程基础 13MenuScript应用
    UG OPEN API编程基础 14API、UIStyler及MenuScript联合开发
    UG OPEN API编程基础 4部件文件的相关操作
    UG OPEN API编程基础 1概述
    16 UG Open的MFC应用
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998449.html
Copyright © 2020-2023  润新知