acwing1207: 大臣的旅费【求树的直径】
这道题目的核心是求树的直径,即树在最长的那条路,这里有一个o(n)的时间复杂度来求树的直径,而且代码非常简洁。方法是这样的:第一步先求出某一个点c的最长路的端点v,然后我们可以证明v是树中某一个直径的端点,然后我们就可以从这个v点开始再求一遍最长路就可以得到直径了;注意:树中的某一个点到另外一个点的路径只有一条那么接下来就是代码了;#include<iostream>#include
·
这道题目的核心是求树的直径,即树在最长的那条路,这里有一个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;
}
更多推荐



所有评论(0)