传送门:洛谷P4408
题目描述
Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:“喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?”一听说要考试,Chris的父母就心急如焚,他们决定在尽量短的时间内找到Chris。他们告诉Chris的老师:“根据以往的经验,Chris现在必然躲在朋友Shermie或Yashiro家里偷玩《拳皇》游戏。现在,我们就从家出发去找Chris,一但找到,我们立刻给您打电话。”说完砰的一声把电话挂了。
Chris居住的城市由N个居住点和若干条连接居住点的双向街道组成,经过街道x需花费Tx分钟。可以保证,任两个居住点间有且仅有一条通路。Chris家在点C,Shermie和Yashiro分别住在点A和点B。Chris的老师和Chris的父母都有城市地图,但Chris的父母知道点A、B、C的具体位置而Chris的老师不知。
为了尽快找到Chris,Chris的父母会遵守以下两条规则:
- 如果A距离C比B距离C近,那么Chris的父母先去Shermie家寻找Chris,如果找不到,Chris的父母再去Yashiro家;反之亦然。
- Chris的父母总沿着两点间唯一的通路行走。
显然,Chris的老师知道Chris的父母在寻找Chris的过程中会遵守以上两条规则,但由于他并不知道A,B,C的具体位置,所以现在他希望你告诉他,最坏情况下Chris的父母要耗费多长时间才能找到Chris?
分析
树的直径题都这么毒瘤么,题面不可读系列
可以将题目的要求拆成两部分 求
最小值的最大值 和
的最大值
求树上最长路径的的话,那就是树的直径了, 因此
必定为树的直径.两遍dfs确定好
与
点即可,
对于
,可以将其拆成两部分,
(P在树的直径上),以及
,对此,枚举直径上的每个点,求出不经过直径其他点最长距离(即为
).比较更新答案即可.
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define IL inline
using namespace std;
IL int read()
{
char c = getchar();
int sum = 0 ,k = 1;
for(;'0' > c || c > '9'; c = getchar())
if(c == '-') k = -1;
for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0';
return sum * k;
}
int to[400005], nxt[400005], val[400005];
int last[200005];
int cnt;
IL void add(int u, int v, int w)
{
to[++cnt] = v; nxt[cnt] = last[u]; val[cnt] = w; last[u] = cnt;
to[++cnt] = u; nxt[cnt] = last[v]; val[cnt] = w; last[v] = cnt;
}
typedef long long ll;
int n, m;
ll dis[200005];
int fa[200005];
bool check[200005];
IL ll min_(ll x, ll y) { return x < y ? x : y; }
IL ll max_(ll x, ll y) { return x > y ? x : y; }
IL void dfs(int u, int &p)
{
if(dis[u] > dis[p]) p = u;
for(int i = last[u], v; (v = to[i]); i = nxt[i])
if(v != fa[u])
{
dis[v] = dis[u] + val[i];
fa[v] = u;
dfs(v, p);
}
}
IL void dfs2(int u, int pre, ll d, ll &maxd)
{
if(d > maxd) maxd = d;
for(int i = last[u], v; (v = to[i]); i = nxt[i])
if(v != pre && !check[v])
dfs2(v, u, d + val[i], maxd);
}
int main()
{
n = read(); m = read();
for(int i = 1, x, y; i <= m; ++i)
{
x = read(); y = read();
add(x, y, read());
}
int S = 0, T = 0;
dfs(1, T);
dis[T] = 0; fa[T] = 0;
dfs(T, S);
for(int i = S; i; i = fa[i])
check[i] = 1;
ll ans = 0, maxd;
for(int i = S; i; i = fa[i])
{
maxd = 0;
dfs2(i, 0, min_(dis[i], dis[S] - dis[i]), maxd);
ans = max_(ans, maxd);
}
ans += dis[S];
printf("%lld\n", ans);
return 0;
}