[CF1041E]Tree Reconstruction

题目大意:有一棵树,现在给你每条树边被去掉时,形成的两个联通块中点的最大的编号分别是多少,问满足条件的树存不存在,存在输出方案

题解:一条边的两个编号中较大的一个一定是$n$,否则无解。

开始构造这棵树,发现一定可以是一条链,可以钦定$n$在链的一端,把较小值(即前缀$max$)排序,每次变化是就把该位赋成变化值,否则就从前面随便取一个没用过的出来(若没有则无法构造)。

为什么一定可以是链呢?发现无法构造的条件是排序后$i>max_i$,而此时也构造不出树(显然)。

卡点:

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 1010
int n;
int s[maxn], p[maxn];
bool used[maxn];
int main() {
	scanf("%d", &n);
	for (int i = 1, a, b; i < n; i++) {
		scanf("%d%d", &a, &b);
		if (a > b) std::swap(a, b);
		if (b != n) {
			puts("NO");
			return 0;
		}
		s[i] = a;
	}
	std::sort(s + 1, s + n);
	for (int i = 1; i < n; i++) {
		if (s[i] != s[i - 1]) used[p[i] = s[i]] = true;
		else {
			bool found = false;
			for (int j = 1; j < s[i]; j++) if (!used[j]) {
				used[p[i] = j] = found = true;
				break;
			}
			if (!found) {
				puts("NO");
				return 0;
			}
		}
	}
	p[n] = n;
	puts("YES");
	for (int i = 1; i < n; i++) {
		printf("%d %d\n", p[i], p[i + 1]);
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Memory-of-winter/p/9830504.html