看上去非常不可做的题
建议手玩
首先考虑无解的情况,考虑树断开一条边之后会怎么样
显然 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