Loading

AT ARC156C Tree and LCS 题解

link

贪心考虑,要使得 \(x, P\) 最小,要么出现的共同节点最少,要么共同节点尽可能出现在某一(些)节点的异侧。从极端情况出发,如果 \(|x| = |P| = 1\),显然 \(\text{LCS} = 1\);如果 \(|x| = |P| = n\),所有点都出现过一次,不可能出现 \(\text{LCS} = 0\) 的情况,如果构造出 \(\text{LCS} = 1\),意味着在 \(x, P\) 中,除了一个相同的路径之外,其余的节点出现位置刚好镜像或者说相反。

构造方法如下:

  1. 任意选取两个叶子,将它们的权值交换
  2. 删掉两个叶子,重复这个过程
  3. 将最后留下的加入答案序列
#include <bits/stdc++.h>

using i64 = long long;

constexpr int N = 5007;

int n;
int ind[N], ans[N];

std::vector<int> adj[N];

void bfs() {
	std::queue<int> q;
	for (int i = 1; i <= n; i++) {
		if (ind[i] == 1)
			q.push(i);
	}
	for (int i = 1; i <= (n / 2); i++) {
		int u1 = q.front(); q.pop();
		int u2 = q.front(); q.pop();
		ans[u1] = u2; ans[u2] = u1;
		for (auto v : adj[u1]) {
			ind[v]--;
			if (ind[v] == 1)
				q.push(v);
		}
		for (auto v : adj[u2]) {
			ind[v]--;
			if (ind[v] == 1)
				q.push(v);
		}
	}
}

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

	std::cin >> n;
	for (int i = 1, u, v; i < n; i++) {
		std::cin >> u >> v;
		adj[u].push_back(v); ind[v]++;
		adj[v].push_back(u); ind[u]++;
	}
	bfs();
	for (int i = 1; i <= n; i++) {
		if (ans[i])
			std::cout << ans[i] << " ";
		else
			std::cout << i << " ";
	}
	std::cout << "\n";
	return 0;
}
posted @ 2025-11-02 19:47  夢回路  阅读(3)  评论(0)    收藏  举报