大臣的旅费____树的直径

蓝桥杯—-大臣的旅费
题目

这里题目没有给出N的范围,略坑。实测N最大值是10000;

由题意得这是一棵最小生成树的结构。求某点到某点的最长距离。
可以用Floyd算法求出各个点到各个点的最小距离,但是由于数据规模10000,而Floyd毕竟是一个O(n^3)时间复杂度算法。因此只能通过75%的数据。


分析可得,题目求的是这个数中距离最远的两个点的距离,即求树的直径,求树的直径的方法是,先从任一点开始,找到距离这个点最远的点,然后,从这个最远的点开始,找到离这个点最远的点。因此,以下代码是先深搜一遍找到最远的点再通过深搜第二次。图的存储方式采用邻接表。邻接矩阵适合稠密图即点少边多的图,邻接表则适合点多变少的稀疏图。对这两种图进行深搜的时间复杂度邻接矩阵为O(n^2),邻接表为O(n+e),e为边的数量。


#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <cstdio>

using namespace std;

struct Edge
{
   // int x;
    int y;//y存储这个边表节点的尾节点
    int v;
    int next;//next存储下个边表节点的数组下标
}edge[100005];

int head[100005], Max , k;
int vis[100005] = {0};

void dfs(int s , int len)
{
    int i , j ;

    vis[s] = true;

    for ( i = head[s] ; i != -1 ; i = edge[i].next )
    {
        //如果这个节点还没被访问过的话
        if ( !vis[edge[i].y] )
        {
            if ( Max < len+edge[i].v )
            {
                Max = len+edge[i].v;
                k = edge[i].y;
            }
            dfs( edge[i].y , len+edge[i].v );
        }

    }
}

int main ()
{
    int N,i,x,y,v,sum;

    scanf ("%d",&N);

    memset(head,-1,sizeof(head));

    Max = 0;

    for ( i = 0 ; i < N-1 ; i++)
    {
        scanf ("%d%d%d",&x,&y,&v);

        edge[i].y = y ;
        edge[i].v = v ;
        edge[i].next = head[x];
        head[x] = i;

        edge[i+N-1].y = x ;
        edge[i+N-1].v = v ;
        edge[i+N-1].next = head[y];
        head[y] = i+N-1;

    }
/*
    for ( i = 1 ; i <= N ; i++)
    {
        cout<<head[i]<<endl;
    }

    cout<<endl;

    for ( i = 0 ; i < 8 ; i++)
    {
        cout<<i<<'\t'<<edge[i].y<<'\t'<<edge[i].next<<endl;
    }
*/
    Max = 0 ;

    dfs(1,0);

    Max = 0;

    memset(vis,0,sizeof(vis));

    dfs(k,0);

    printf("%d\n",(Max*Max+21*Max)/2);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值