看上去非常不可做的题
建议手玩
首先考虑无解的情况,考虑树断开一条边之后会怎么样
显然 n 一定是其中一部分的答案,另一部分的答案不确定
所以当 存在 i 使得 ai ≠ n 且 bi ≠ n 时,就没有合法的答案
似乎没有什么了,继续考虑如何构造
当一个点作为 ai 出现过多次时(假设有 x 次),那么它到 n 号点路径上就至少要有 x 条边,且这条路径上的点编号 <= ai
发现按上述条件构造的话,总觉得会被卡掉,就大概是 ai 到 n 路径上边数多于 x
想一想好像这样构造确实是没有问题的,不过 “至少” 这个条件就变成了 “恰好”
所以我们又发现了一个无解的情况,那就是当一个点作为 ai 出现的次数超过它的编号大小的话,也是会无解的
这样这题就可做了
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
using namespace std;
const int MAXN = 1005;
int n;
int a[MAXN], b[MAXN], dst[MAXN];
bool set[MAXN];
inline void make_path(int x) {
int lst = x, rem = dst[x];
for(int i = 1; i < n; ++i) {
if(set[i]) {
if(rem != 1) {
set[i] = false;
printf("%d %d\n", lst, i);
lst = i;
--rem;
}
}
if(rem == 1) {
printf("%d %d\n", lst, n);
return;
}
}
return;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) set[i] = true;
for(int i = 1; i < n; ++i) {
scanf("%d%d", &a[i], &b[i]);
++dst[a[i]];
set[a[i]] = false;
if(b[i] != n) {
puts("NO");
return 0;
}
}
sort(a + 1, a + n);
for(int i = 1; i < n; ++i) {
if(i > a[i]) {
puts("NO");
return 0;
}
}
puts("YES");
for(int i = 1; i <= n; ++i) {
if(!dst[i]) continue;
if(dst[i] == 1) {
printf("%d %d\n", i, n);
} else {
make_path(i);
}
}
return 0;
}
原文:https://www.cnblogs.com/xcysblog/p/9678332.html