总结:有了思路后强行模拟出来了过程,其实可以更简单,(但本人貌似很享受模拟的过程)。
大意:求构造n-1条边的树,给出n-1对 数,表示删除第i的边后,两个联通块各自最大的顶点编号。
思路:去边后必有一个联通块的最大编号是n,否则必定是不能构造的。第一次出现的二元关系。。。。太多了,反正思路就这样。
int a[N];
int main()
{
int n;
while (cin >> n)
{
set<int> stt;
map<pii, int> mp;
int x, y;
int fg = 1;
f(i, 1, n - 1)
{
scanf("%d%d", &x, &y);
if (y != n)fg = 0;//no
if (mp[make_pair(x, y)])a[x]++;//需要有一个比它小的连在中间
mp[make_pair(x, y)]++;
stt.insert(x);
}
if (!fg) { puts("NO");continue; }
set<int> st;
f(i, 1, n - 1)
{
if (!stt.count(i))st.insert(i);//选出没直接限制的
}
vector<pii> ans;
fg = 1;
f(i, 1, n - 1)
{
set<int> tmp;tmp.insert(i);
f(j, 1, a[i])//i到n的路径被替换
{
auto it = st.begin();
if (*it > i) { fg = 0;goto hh; }
tmp.insert(*it);
st.erase(it);
}
//替换路径
if (tmp.size() == 1)continue;
stt.erase(i);
stt.insert(*tmp.begin());
while (tmp.size() >= 2)
{
auto it = tmp.begin();
ans.emplace_back(make_pair(*it, *(it++)));
tmp.erase(tmp.begin());
}
}
hh:if (!fg)puts("NO");
else
{
puts("YES");
for (auto I : stt)cout << n << " " << I << endl;
for (auto I : ans)cout << I.first << " " << I.second << endl;
}
}
return 0;
}