树的直径的模板

  今天写了道树的直径的题,其实以前也看过,那时候并不专注,没看懂,现在发现就只是两遍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%的数据,要注意

猜你喜欢

转载自blog.csdn.net/PWeiDa/article/details/82289680