今天写了道树的直径的题,其实以前也看过,那时候并不专注,没看懂,现在发现就只是两遍bfs的事,但是原理并没有这么简单
我来简单说一下
我们随便在树中找一个点u,然后开始bfs找到最远的一点v,在之后就是关键部分,我们再从v开始bfs,找到的最远距离就是直径。
说到这里,就有很多人看不懂了,因为并不能说明v就是直径的一个端点,这里要通过反证法来证明
来个链接:https://blog.csdn.net/qianguch/article/details/78216860
看不懂也不要紧,只要记住v就是直径的一个端点,然后再一遍bfs就可以得出答案
代码如下:
#include <map>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct edge
{
int to;
int w;
};
vector<edge>e[100000];
int vis[100000];
ll ans,dis[100000];
void add(int u,int v,int w)
{
edge t;
t.to=v;
t.w=w;
e[u].push_back(t);
}
int bfs(int x)
{
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
queue<int>q;
int num;
q.push(x);
vis[x]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
if(dis[u]>ans)
{
ans=dis[u];//这里是距离
num=u;
}
int len=e[u].size();
for(int i=0;i<len;i++)
{
edge t=e[u][i];
if(!vis[t.to])
{
dis[t.to]=dis[u]+t.w;
vis[t.to]=1;
q.push(t.to);
}
}
}
return num;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
ans=-99999;
int t=bfs(1);//最远的一点,也就是直径的一个端点
ans=-99999;//第一遍的ans是没有作用的,要重新更新
bfs(t);
printf("%lld\n",ans);
return 0;
}
这里的ans=-99999有点坑,第一遍写的时候这里卡了4%的数据,要注意