题目:传送
题意:
给一棵树,求树的直径。
思路:
观察:从任何一个点出发的最远点一定是一条直径的端点。
证明:
1.点在一条直径上
2.点不在直径上一定和一条直径交叉
所以,我们把这些边存到邻接表中,任选一个起点,进行2次bfs。就可以啦。
上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
struct edge{
int from,to,next,w;
}e[100005];
int tot=0;
int first[50005];
int dis[50005];
int n,m;
void add(int from,int tt,int co)
{
e[tot].to=tt;
e[tot].w=co;
e[tot].next=first[from];
first[from]=tot++;
}
int bfs(int s){
queue<int> q;
memset(dis,-1,sizeof(dis));
dis[s]=0;
int maxd=0;
q.push(s);
int pos=s;
while(!q.empty())
{
int temp=q.front();
q.pop();
if(dis[temp]>maxd)
{
maxd=dis[temp];
pos=temp;
}
for(int i=first[temp];i!=-1;i=e[i].next){
if(dis[e[i].to]== -1)
{
dis[e[i].to]=dis[temp]+e[i].w;
q.push(e[i].to);
}
}
}
//printf("%d\n",pos);
return pos;
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
memset(first,-1,sizeof(first));
int u,v,cost;
char c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d %c",&u,&v,&cost,&c);
add(u,v,cost);
add(v,u,cost);
}
printf("%d",dis[bfs(bfs(u))]);
}
}
/*7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S*/