洛谷题单指南-图论之树-P4408 [NOI2003] 逃学的小孩
原题链接:https://www.luogu.com.cn/problem/P4408
题意解读:树形结构中三个点C、A、B,C->A的路径小于C->B的路径,求C->A->B的可能的最长路径。
解题思路:
1、C->A以及C->B的距离有限制,但是A->B是没有限制的,显然越大越好,那么A->B应该取直径
2、接下来,C应该是距离直径两个端点距离较小的最大值
3、从直径两个端点分别跑一遍dfs,可以求出每个点到直径端点的距离
4、最终答案,枚举每一个点,取与两个直径端点距离较小的最大值,再加上直径长度
100分代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200005;
struct Node
{
int v, w;
};
vector<Node> g[N];
int st, ed; //直径端点
LL maxdist; //直径长度
LL d1[N], d2[N]; //直径两个端点到所有点的距离
int n, m;
void dfs1(int u, int p, LL d, int w)
{
if(d > maxdist)
{
ed = u;
maxdist = d;
}
for(auto item : g[u])
{
int v = item.v, w = item.w;
if(v == p) continue;
dfs1(v, u, d + w, w);
}
}
void dfs2(LL f[N], int u, int p, LL d)
{
f[u] = d;
for(auto item : g[u])
{
int v = item.v, w = item.w;
if(v == p) continue;
dfs2(f, v, u, d + w);
}
}
int main()
{
cin >> n >> m;
while(m--)
{
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
}
st = 1;
dfs1(st, 0, 0, 0);
st = ed, maxdist = 0;
dfs1(st, 0, 0, 0);
dfs2(d1, st, 0, 0);
dfs2(d2, ed, 0, 0);
LL res = 0;
for(int i = 1; i <= n; i++)
{
res = max(res, min(d1[i], d2[i]) + maxdist);
}
cout << res;
return 0;
}
浙公网安备 33010602011771号