Atcoder256 E

  题意:给我们一个序列,表示第\(i\)个人想要在\(X_i\)人前面获得糖果,不然就会获得不满意度。要我们求出来这个序列中的最小不满意度是多少。
  思路:因为这个题假设每一个人入度都为\(1\)的话,它整体就是一个环,所以现在去考虑序列中存在入度为\(0\)的点。我们考虑用\(DSU\)来存储边得关系

#include <bits/stdc++.h>

using i64 = long long;

int main() {
	std::cin.tie(nullptr)->sync_with_stdio(false);

	int n; std::cin >> n;

	std::vector<int> a(n + 1), f(n + 1), c(n + 1);
	std::iota(f.begin(), f.end(), 0);

	for (int i = 1; i <= n; i ++ ) std::cin >> a[i];
	for (int i = 1; i <= n; i ++ ) std::cin >> c[i];

	std::function<int(int)> find = [&] (int x) -> int {
		return x == f[x] ? f[x] : f[x] = find(f[x]);
	};

	auto same = [&] (int u, int v) -> bool {
		return find(u) == find(v);
	};

	auto merge = [&] (int u, int v) -> void {
		int fu = find(u), fv = find(v);
		if (fu == fv) return ;
		f[fv] = fu;
	};

	i64 ans = 0;
	for (int i = 1; i <= n; i ++ ) {
		if (!same(i, a[i])) {
			merge(i, a[i]);
			continue;
		}
		int cur = c[i], v = i;
		do {
			v = a[v];
			cur = std::min(cur, c[v]);
		}while(v != i);
		ans += cur;
	}
	std::cout << ans << "\n";
	return 0;
}
posted @ 2022-06-27 21:24  浅渊  阅读(36)  评论(0)    收藏  举报