蓝桥杯—-大臣的旅费
这里题目没有给出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;
}