这道题目的核心是求树的直径,即树在最长的那条路,这里有一个o(n)的时间复杂度来求树的直径,而且代码非常简洁。

方法是这样的:第一步先求出某一个点c的最长路的端点v,然后我们可以证明v是树中某一个直径的端点,然后我们就可以从这个v点开始再求一遍最长路就可以得到直径了;

注意:树中的某一个点到另外一个点的路径只有一条

那么接下来就是代码了;

#include<iostream>
#include <vector>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;

const int N=100010;

struct p{
    int num,w;//num为下一个点的遍号,w为路长
};

vector<vector<p>> list(N);//邻接表存储图
ll dist[N];//从起点到另外一个点的距离
int st[N];//记录每个点是否走过
int n;

void dfs(int id,ll w){//dfs遍历图
    
    st[id]=1;
    dist[id]=w;
    
    for(int i=0;i<list[id].size();i++){
        
        if(!st[list[id][i].num])
           dfs(list[id][i].num,list[id][i].w+w);
        
    }
    
}

int main(){
    
    cin>>n;
    
    for(int i=0;i<n-1;i++){//接收图
        
        int a,b,w; cin>>a>>b>>w;
        
        list[a].push_back({b,w});
        list[b].push_back({a,w});
    }
    
    dfs(1,0);
    
    int id=1;
    
    for(int i=1;i<=n;i++)//找到最长路的端点
        if(dist[id]<dist[i])
            id=i;
    
    memset(st,0,sizeof st);//记得更新st数组
    
    dfs(id,0);//再求一遍
    
    ll max1=-1;
    
    for(int i=1;i<=n;i++){//找到最长路
        
        if(max1<dist[i])
           max1=dist[i];
    }
    
    cout<<max1*10+(max1*max1+max1)/2;
    
}

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐