There is a tree of n vertices. For each vertex a list of all its successors is known (not only direct ones). It is required to restore the tree or to say there is no such tree.

Input

The first line contains a single integer n (1 ≤ n ≤ 1000) — the number of vertices in the tree.

Each of the next n lines contains an integer ci (0 ≤ ci ≤ n) — the number of successors of vertex i, and then ci distinct integers aij (1 ≤ aij ≤ n) — the indices of successors of vertex i.

Output

If the answer does not exist, output «NO».

Otherwise, in the first line output «YES», and then output n - 1 lines containing two integers each — indices of parent and child. Pairs (parent, child) can be output in any order.

Examples

Input
5
4 2 3 4 5
3 3 4 5
2 4 5
1 5
0
Output
YES
1 2
2 3
3 4
4 5
Input
5
4 2 3 4 5
3 3 4 5
0
1 5
0
Output
YES
1 2
2 3
2 4
4 5
Input
3
3 2 3 1
3 3 1 2
3 1 2 3
Output
NO

细节太多,大致先按子孙的数量排序。。。
还是请看我的代码吧,写这篇博客,主要是提醒一下坑点。
1.有环
2.建出来好几课树
3.自己不能当自己的儿子。
4.每个儿子都不能漏
数据一组:

7
5 2 3 4 5 6
2 4 5
2 6 7
0
0
0
0

还要注意并查集不能压缩路径

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#define fuck(x) cout<<#x<<" = "<<x<<endl;
#define ls (t<<1)
#define rs ((t<<1)+1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = ;
const int inf = 2.1e9;
const ll Inf = ;
const int mod = ;
const double eps = 1e-;
const double pi = acos(-);
bool vis[maxn];
int num[maxn];
int f[maxn];
struct node
{
int id,sz;
}a[maxn];
vector<int>v[maxn];
int n,m; bool cmp(node a,node b){
return a.sz<b.sz;
} int mx=;
int getf(int x,int t){
if(t==mx){return -;}
if(x==f[x])return x;
return getf(f[x],t+);
} int get_num(int x,int t){
if(t==mx){return -;}
num[x]++;
if(x==f[x]){return x;}
return get_num(f[x],t+);
} vector<int>tt;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&m);f[i]=i;
for(int j=;j<=m;j++){
int x;
scanf("%d",&x);
v[i].push_back(x);
a[i].sz++;
}
a[i].id=i;
} sort(a+,a++n,cmp);
bool flag=true;
for(int i=;i<=n;i++){
int siz = a[i].sz;
int id=a[i].id;
for(int j=;j<siz;j++){
vis[v[id][j]]=true;
}
vis[id]=true;
for(int j=;j<siz;j++){
int t1=getf(v[id][j],);
if(id==v[id][j]||t1==-||!vis[t1]){flag=false;break;}
if(t1==v[id][j]){tt.push_back(t1);}
}
int sz=tt.size();
for(int j=;j<sz;j++){
f[tt[j]]=id;
}
tt.clear();
if(!flag){break;}
memset(vis,,sizeof(vis));
} int rec=;
for(int i=;i<=n;i++){
if(f[i]==i){rec++;}
get_num(i,);
}
for(int i=;i<=n;i++){
if(num[i]!=v[i].size()+){flag=false;}
}
if(rec!=){flag=false;} if(flag){
printf("YES\n");
for(int i=;i<=n;i++){
if(f[i]!=i){printf("%d %d\n",f[i],i);}
}
}
else {
printf("NO\n");
} return ;
}

Tree Restoration Gym - 101755F (并查集)的更多相关文章

  1. Is It A Tree? POJ - 1308(并查集判树)

    Problem Description A tree is a well-known data structure that is either empty (null, void, nothing) ...

  2. 【bzoj2870】最长道路tree 树的直径+并查集

    题目描述 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数. 输入 第一行N 第二行N个数分别表示1~N的点权v[i] 接下来N-1行每 ...

  3. 【51nod1253】Kundu and Tree(容斥+并查集)

    点此看题面 大致题意: 给你一棵树,每条边为黑色或红色, 求有多少个三元组\((x,y,z)\),使得路径\((x,y),(x,z),(y,z)\)上都存在至少一条红色边. 容斥 我们可以借助容斥思想 ...

  4. BZOJ 2870: 最长道路tree 树的直径+并查集

    挺好的一道题. 把所有点都离线下来,一个个往里加入就行了. #include <cstdio> #include <algorithm> #define N 100003 #d ...

  5. BZOJ 2654 tree(二分答案+并查集)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2654 [题目大意] 给你一个无向带权连通图,每条边是黑色或白色. 让你求一棵最小权的恰 ...

  6. Hdu.1325.Is It A Tree?(并查集)

    Is It A Tree? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  7. Is It A Tree?(并查集)

    Is It A Tree? Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26002   Accepted: 8879 De ...

  8. CF109 C. Lucky Tree 并查集

    Petya loves lucky numbers. We all know that lucky numbers are the positive integers whose decimal re ...

  9. Codeforces Gym 100463E Spies 并查集

    Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Desc ...

随机推荐

  1. Jenkins+PowerShell持续集成环境搭建(八)邮件通知

    1. 默认邮件功能: Jenkins自带的邮件功能比较简单,配置如下: 设置默认发件人地址: 2. Email Extension Plugin 为了能够更加灵活地使用邮件功能,需要安装Email E ...

  2. 吴恩达deeplearning之CNN—卷积神经网络

    https://blog.csdn.net/ice_actor/article/details/78648780 个人理解: 卷积计算的过程其实是将原始的全连接换成了卷积全连接,每个kernel为对应 ...

  3. 三星Galaxy S10可望率先应用于1TB的手机内存

    导读 三星电子(Samsung Electronics)1月30日宣布,已经开始量产业界首款容量高达1TB的嵌入式通用闪存存储器(embedded Universal Flash Storage,eU ...

  4. Windows服务一直“正在启动”怎么杀

    转载:https://blog.csdn.net/huanglong8/article/details/71156848 PS:cmd 记得使用 管理员身份运行 这里需要通过控制台 命令行来查询PID ...

  5. 51Nod1778 小Q的集合 【组合数】【Lucas定理】

    题目分析: 题解好高深...... 我给一个辣鸡做法算了,题解真的看不懂. 注意到方差恒为$0$,那么其实就是要我们求$\sum_{i=0}^{n}\binom{n}{i}(i^k-(n-i)^k)^ ...

  6. Ionic3实现选项卡切换可以重新加载echarts

    要求 选项卡每切换一次,就加载对应的一个echarts 图,要有一开始的动画效果效果如下: 注意点 1.echarts要想每次都能重新加载,需要移除"_echarts_instance_&q ...

  7. 可前端解密的加密方法探讨和str_replace和preg_replace分析

    目的: 对字符串‘123456’进行后端加密,前端js可解密出真实字符 测试代码php: static $hashMap = array( '0' => '4', '1' => '9', ...

  8. 脚本监控web服务器,工作不正常发邮件提醒

    背景介绍公司有多个web网站,没有配置监控服务,每天都需要定时检查服务器是否工作正常.低效耗时. 代码片段 #!/bin/bash # Author Jerry.huang (Email:Jerry. ...

  9. NOIP2018联赛总结

    NOIP2018联赛总结 Day 0 打了几个模板,看了一下别人的博客,背了一下vimrc Day 1 到了考场,先把vimrc配好 打开题目一先把三道题瞄了一眼,\(T1\)似乎是NOIP原题,\( ...

  10. Outsider(HNOI2019)

    这不是一篇退役记,因为NOIP2018之后就写完了. Day-1 清明时节雨纷纷. 最后的时光,应该是怎么样的呢? 是像水滴一样,悄无声息地从指缝中溜走 还是如火焰一般,燃烧着最后的留恋? 晚上一直在 ...