「UVA 12161」Ironman Race in Treeland

Posted -wallace-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「UVA 12161」Ironman Race in Treeland相关的知识,希望对你有一定的参考价值。

Description

给定一个 (n) 个结点的树,每条边有两个属性:长度 (L) 和花费 (D)

现给定最大花费值 (m),求出花费总和不超过 (m) 的路径中长度的最大值。

Hint

(1le nle 3 imes 10^4, 1le mle 10^8, 1le L,Dle 10^3)

Solution

这种树上路径的问题,不难想到 点分治

难点在于如何得到经过根的最优的路径。

我们一个个子结点来看,假如现在处理到子结点为 (x_k),如下图:

技术图片

那么 (x_1, x_2,cdots,x_{k-1}) 的子树已经处理完了。

现在枚举子树 (x_k) 中的所有一个端点为根的路径,当枚举到一条路径的信息为 ((D^prime, L^prime)),我们就在子树 (x_1,x_2,cdots, x_{k-1}) 中的所有路径信息中匹配——找到其中 (D)(le m - D^prime) 的所有路径中 (L) 值的最大值。

这样的话,处理方式就非常多了,比较好的做法可以平衡树,但这里介绍一种虽然效率稍劣但十分简单好理解且细节极少的 动态开点线段树 做法。

回到原来那个匹配的问题:我们把前 (k-1) 个子树的路径信息存入一个动态开点线段树中,对 (D) 值域(位置)开线段树,结点维护 (L) 的最大值。那么就可以求出位置 ([0,D^prime -1]) 的最大值,然后子树 (x_k) 处理完后,在把其中的路径信息以 (D) 为位置,(L) 为值,做 单点最值操作,即 ( ext{val}_D leftarrow max( ext{val}_D, L))。还有就是记得及时清空。

这样的算法复杂度是多少呢?动态开点线段树的空间一次修改是最大多开 (log U)(U) 为值域,下同)个结点,所以空间复杂度为 (O(nlog U))

由于深度也是最大 (log U) 层,所以时间复杂度为 (O(nlog n log U))

Code

跑了 380ms,效率还是挺可观的。

#include <algorithm>
#include <cstdio>
#include <utility>
#include <vector>

using namespace std;
const int N = 3e4 + 5;

namespace dysgt {
	const int LogU = 27;
	const int S = N * LogU;
	const int Lim = 1e8;
	int lc[S], rc[S];
	int maxv[S];
	int total = 0;
	int root = 0;
	
	inline void destroy(int x) {
		lc[x] = rc[x] = maxv[x] = 0;
	}
	inline void modify(int p, int v) {
		int l = 0, r = Lim;
		if (!root) root = ++total;
		for (register int x = root; l != r; ) {
			maxv[x] = max(maxv[x], v);
			int mid = (l + r) >> 1;
			if (p <= mid) x = !lc[x] ? (lc[x] = ++total) : lc[x], r = mid;
			else x = !rc[x] ? (rc[x] = ++total) : rc[x], l = mid + 1;
		}
	}
	int getMax(int L, int R, int l = 0, int r = Lim, int x = root) {
		if (!x) return 0;
		if (L <= l && r <= R) return maxv[x];
		int ret = 0, mid = (l + r) >> 1;
		if (l <= mid) ret = max(ret, getMax(L, R, l, mid, lc[x]));
		if (r > mid) ret = max(ret, getMax(L, R, mid + 1, r, rc[x]));
		return ret;
	}
	void _S_clr(int x) {
		if (!x) return;
		_S_clr(lc[x]), _S_clr(rc[x]);
		destroy(x);
	}
	inline void clear() {
		_S_clr(root);
		root = total = 0;
	}
}

int n, m;
struct edge { int to, len, dam; };
vector<edge> G[N];

bool centr[N];
int maxp[N], size[N];
int root;
int getSize(int x, int f) {
	size[x] = 1;
	for (auto y : G[x])
		if (y.to != f && !centr[y.to])
			size[x] += getSize(y.to, x);
	return size[x];
}
void getCentr(int x, int f, int t) {
	maxp[x] = 0;
	for (auto y : G[x]) {
		if (y.to == f || centr[y.to]) continue;
		getCentr(y.to, x, t);
		maxp[x] = max(maxp[x], size[y.to]);
	}
	maxp[x] = max(maxp[x], t - size[x]);
	if (maxp[x] < maxp[root]) root = x;
}

pair<int, int> path[N];
int tot;
void getPaths(int x, int f, int l, int d) {
	if (d > m) return;
	path[++tot] = {d, l};
	for (auto y : G[x])
		if (y.to != f && !centr[y.to])
			getPaths(y.to, x, l + y.len, d + y.dam);
}

int ans;
void solve(int x) {
	getSize(x, 0);
	maxp[root = 0] = N;
	getCentr(x, 0, size[x]);
	int s = root;
	centr[s] = true;
	
	for (auto y : G[s])
		if (!centr[y.to])
			solve(y.to);
	
	dysgt::clear(), dysgt::modify(0, 0);
	for (auto y : G[s]) {
		if (centr[y.to]) continue;
		tot = 0, getPaths(y.to, x, y.len, y.dam);
		for (register int i = 1; i <= tot; i++)
			ans = max(ans, dysgt::getMax(0, m - path[i].first) + path[i].second);
		for (register int i = 1; i <= tot; i++)
			dysgt::modify(path[i].first, path[i].second);
	}
	
	centr[s] = false;
}

signed main() {
	int T; scanf("%d", &T);
	for (register int tc = 1; tc <= T; tc++) {
		scanf("%d%d", &n, &m);
		for (register int i = 1; i <= n; i++) {
			G[i].clear();
			maxp[i] = size[i] = 0;
			centr[i] = false;
		}
		
		for (register int i = 1; i < n; i++) {
			int u, v, l, d;
			scanf("%d%d%d%d", &u, &v, &d, &l);
			G[u].push_back({v, l, d});
			G[v].push_back({u, l, d});
		}
		
		ans = 0, solve(1);
		printf("Case %d: %d
", tc, ans);
	}
	return 0;
}

以上是关于「UVA 12161」Ironman Race in Treeland的主要内容,如果未能解决你的问题,请参考以下文章

UVA 12034 Race

UVa 12034 Race (递推+组合数学)

uva 12034 Race

Uva11762 Race to 1——有向无环图&&记忆化搜索

UVA 12034 Race (递推神马的)

UVA 11762 Race to 1(记忆化+期望)