题目描述
blablabla
样例
blablabla
算法1
(深搜)
对每个点都做一遍深搜,dfs(u)返回u点为起点能走到的最大距离,每一个搜一遍就能得出整棵树的最大直径。
超时,过6/10数据
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int e[2 * N], ne[2 * N], head[N], idx, n, w[2 * N], dis[N];
bool isVisited[N];
void add(int a, int b, int c){
e[idx] = b, ne[idx] = head[a], w[idx] = c, head[a] = idx++;
}
int dfs(int x){
int max_r = 0;
isVisited[x] = true;
for(int i = head[x]; i != -1; i = ne[i]){
int j = e[i], temp = 0;
if(!isVisited[j]){
//cout << "j是" << j << ", ";
isVisited[j] = true;
temp = dfs(j) + w[i];
max_r = max(max_r, temp);
isVisited[j] = false;
}
}
isVisited[x] = false;
dis[x] = max(dis[x], max_r);
//cout << "dis[" << x << "]是" << dis[x] << endl;
return max_r;
}
int main(){
ios::sync_with_stdio(false);
memset(head, -1, sizeof head);
cin >> n;
for(int i = 0; i < n - 1; i++){
int a, b, c;
cin >> a >> b >> c;
add(a, b, c), add(b, a, c);
}
for(int i = 1; i <= n; i++){
//memset(dis, 0, sizeof dis);
dfs(i);
}
//dfs(2);
int Max = -1e9;
for(int i = 1; i <= n; i++) Max = max(Max, dis[i]);//, cout << "dis[" << i << "]是" << dis[i] << endl;
cout << (1 + Max) * Max / 2 + 10 * Max;
return 0;
}
算法2
(优化的深搜)
树的最大直径:随便从一个点开始,找到离这个点开始能走到的最远的点。找到后用这个点再搜一遍,再搜到最远的点就是树的最大直径。
C++ 代码
// 如何求树的最大直径:任选一点开始深度搜索,找到离这个点最远的点;找到后从这个点再搜一次,再搜到最远的点就是树的最大直径
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
int e[2 * N], ne[2 * N], head[N], idx, n, w[2 * N];
ll dis[N];
bool isVisited[N];
int longest_point;
ll ans;
ll max(ll a, ll b){
return a > b ? a : b;
}
void add(int a, int b, int c){
e[idx] = b, ne[idx] = head[a], w[idx] = c, head[a] = idx++;
}
// dfs(u)返回终点是u的最大路程, 注意,不是当前搜索下起点是u的最大路程
int dfs(int u, int distance){
isVisited[u] = true;
for(int i = head[u]; i != -1; i = ne[i]){
int j = e[i];
if(!isVisited[j]){
isVisited[j] = true;
dis[j] = max(distance + w[i], dis[j]);
dfs(j, dis[j]);
isVisited[j] = false;
}
}
return dis[u];
}
int main(){
ios::sync_with_stdio(false);
memset(head, -1, sizeof head);
cin >> n;
for(int i = 0; i < n - 1; i++){
int a, b, c;
cin >> a >> b >> c;
add(a, b, c), add(b, a, c);
}
dfs(1, 0); // 找到了离这个点最远的一个点,返回其总距离,可以从任任意点开始搜索
ll temp_max = -1e9;
for(int i = 1; i <= n; i++){
if(dis[i] > temp_max) longest_point = i, temp_max = dis[i];
}
memset(dis, 0, sizeof dis);
memset(isVisited, false, sizeof isVisited);
dfs(longest_point, 0); // 再用从离初次搜索的点最远的点做一遍深搜,就能找到树的最大直径
temp_max = -1e9;
for(int i = 1; i <= n; i++){
if(dis[i] > temp_max) longest_point = i, temp_max = dis[i];
}
cout << (ll)(1 + temp_max) * temp_max / 2 + 10 * temp_max;
return 0;
}