0 pts求调
查看原帖
0 pts求调
573963
wbh20090611楼主2024/8/12 08:45

点分治

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int N = 200005, M = 1000006;
map<int, int> s[M];
vector<pair<int,int > > e[N];
int n, k, f[N], dis[N], dep[N], size[N], son[N], dfn[N], top[N], lll, ans = INT_MAX;
//树链剖分 
void ddffss(int x, int fa)
{
	dep[x] = dep[fa] + 1;
	size[x] = 1;
	f[x] = fa;
	for (auto i : e[x])
	{
		if (i.fi != fa)
		{
			dis[i.fi] = dis[x] + i.se;
			ddffss(i.fi, x);
			size[x] += size[i.fi];
			if (size[son[x]] < size[i.fi])
				son[x] = i.fi;
		}
	}
}
void ddffss1(int x, int fa)
{
	top[x] = fa;
	dfn[x] = ++lll;
	if (son[x] > -1)
		ddffss1(son[x], fa);
	else return;
	for (auto i : e[x])
		if (i.fi != f[x] && i.fi != son[x])
			ddffss1(i.fi, i.fi);
}
//树链剖分求 LCA 
int lca(int a, int b)
{
	while(top[a] != top[b])
	{
		if (dep[top[a]] < dep[top[b]])
			swap(a, b);
		a = f[top[a]];
	}
	if (dep[a] < dep[b])
		return a;
	return b;
}
void add(map<int, int> &a, map<int, int> &b, int x)
{
	for (auto i : a)
		if (i.fi <= k && b.count(k - i.fi))
			ans = min(i.se + b[k - i.fi] - 2 * dep[x], ans);
	for (auto i : b)
	{
		if (a.count(i.fi))
			a[i.fi] = min(a[i.fi], i.se);
		else
			a[i.fi] = i.se;
	}
	b.clear();
}
void dfs(int x)
{
	s[x][dis[x]] = dep[x];
	if (son[x] == -1)
		return;
	dfs(son[x]);
	add(s[x], s[son[x]], x);
	for (auto i : e[x])
	{
		if (i.fi != f[x] && i.fi != son[x])
		{
			dfs(i.fi);
			add(s[x], s[i.fi], x);
		}
	}
}
int main()
{
	memset(son, -1, sizeof son);
	cin >> n >> k;
	for (int i = 1, u, v, w; i < n; i++)
	{
		scanf("%d%d%d", &u, &v, &w);
		e[u].push_back({v, w});
		e[v].push_back({u, v});
	}
	ddffss(0, 0);
	ddffss1(0, 0);
	dfs(0);
	if (ans != 0x3f3f3f3f)
		cout << ans;
	else cout << -1;
}
2024/8/12 08:45
加载中...