P1099 [NOIP 2007 提高组] 树网的核

链接

https://www.luogu.com.cn/problem/P1099

题目

思路

思路对的,有些地方想的不严谨,但是看评论区证了。 题目有提示:虽然核不唯一,但是最小偏心距唯一。所以想到先找直径,然后再遍历求解。



比如这张图来说,对于i,j两点很显然只要满足|dist[j]-dist[i]|<=s,就求max(树枝长度,首到i的距离,j到尾的距离)。
比如:如果dist(2,4)<s那么当前段的最小偏心距就是max(dist(1,2),dist(2,q),dist(3,p),dist(3,5));

解释一下代码:前半段是利用dfs找到直径两端端点;然后再找到直径间的路径;最后求min(max(all))

代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#include<string.h>
#include<limits.h>
#include<string>
#include<vector>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
#define int long long 


const int N = 310;
struct edge { int to, val; edge() {}; edge(int t, int v) :to(t), val(v) {} };
vector<edge>e[N];
int dist[N];
int nex[N];

void dfs(int u, int fa, int d)
{
	dist[u] = d;
	for (edge i : e[u])
		if (i.to != fa)dfs(i.to, u, i.val+d);
}

bool findWay(int st, int ed, int now, int fa)
{
	if (now == ed)
		return true;
	for (edge i : e[now])
		if (i.to != fa)
			if (findWay(st, ed, i.to, now))
			{
				nex[now] = i.to;
				return true;
			}
	return false;
}

int waying[N];

int cal(int now, int fa, int d)
{
	int ans = d;
	int delta = 0;
	for (edge i : e[now])
	{
		if (i.to == fa)continue;
		else if (e[i.to].size() == 1)delta=i.val;
		else  delta = max(delta, cal(i.to, now, i.val));
	}
	return ans+delta;
}
int getmax(int s, int t)
{
	int ans = waying[s];
	while (s != t)
	{
		s = nex[s];
		ans = max(waying[s],ans);
	}
	return ans;
}
signed main()
{
	int n, sway; cin >> n >> sway;
	for (int i = 1; i < n; i++)
	{
		int st, ed, dis;
		cin >> st >> ed >> dis;
		e[st].push_back(edge(ed, dis)),
			e[ed].push_back(edge(st, dis));
	}
	dfs(1, -1, 0);
	int s = 1;
	for (int i = 1; i <= n; i++)
		if (dist[i] > dist[s])
			s = i;
	dfs(s, -1, 0);
	int t = s;
	for (int i = 1; i <= n; i++)
		if (dist[i] > dist[t])
			t = i;
    //以上是求出两端端点
	findWay(s, t, s, -1);
    //以上是求出路径
	int ptr = nex[s];
	int fa = s;
	while (ptr != t)
	{
		for (edge i : e[ptr])
		{
			if (i.to != fa and i.to != nex[ptr])
				waying[ptr] = max(waying[ptr], cal(i.to, ptr, i.val));
		}
		fa = ptr;
		ptr = nex[ptr];
	}
    //以上是求出该路径各个端点上的其他路径长度的**最大值**
	int ans = LLONG_MAX;
	int lef = s, rig = s;
	while (rig != t)
	{
		while (rig!=t and 0-dist[lef] + dist [nex[rig]] <= sway)rig = nex[rig];
		ans = min(ans, max(0-dist[s] + dist[lef], max(getmax(lef, rig), dist[t]-dist[rig])));
		lef = nex[lef];
	}
    //以上是求答案,注意是s->t,lef->rig。
	cout << ans;



	return 0;
}

posted @ 2025-02-14 21:06  WHUStar  阅读(4)  评论(0编辑  收藏  举报