• 【洛谷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;
    }
    
  • 相关阅读:
    简单的HelloWorld
    jsp获取绝对路径
    EasyUI validType属性
    Django meida(admin后台上传图片并可访问)
    postgresql char 与 varchar的区别
    git pull 源成分支遇到“There is no tracking information for the current branch.”错误
    Centos安装Pillow模块出错解决办法
    centos7网络配置
    表格排序插件tablesorter的初步使用介绍
    linux编译安装指定版本的python
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998450.html
Copyright © 2020-2023  润新知