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
54 2 3 4 53 3 4 52 4 51 50

Output
YES1 22 33 44 5

Input
54 2 3 4 53 3 4 501 50

Output
YES1 22 32 44 5

Input
33 2 3 13 3 1 23 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 = 1024;
const int inf = 2.1e9;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1);
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=1001;
int getf(int x,int t){if(t==mx){return -1;}if(x==f[x])return x;return getf(f[x],t+1);
}int get_num(int x,int t){if(t==mx){return -1;}num[x]++;if(x==f[x]){return x;}return get_num(f[x],t+1);
}vector<int>tt;
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&m);f[i]=i;for(int j=1;j<=m;j++){int x;scanf("%d",&x);v[i].push_back(x);a[i].sz++;}a[i].id=i;}sort(a+1,a+1+n,cmp);bool flag=true;for(int i=1;i<=n;i++){int siz = a[i].sz;int id=a[i].id;for(int j=0;j<siz;j++){vis[v[id][j]]=true;}vis[id]=true;for(int j=0;j<siz;j++){int t1=getf(v[id][j],0);if(id==v[id][j]||t1==-1||!vis[t1]){flag=false;break;}if(t1==v[id][j]){tt.push_back(t1);}}int sz=tt.size();for(int j=0;j<sz;j++){f[tt[j]]=id;}tt.clear();if(!flag){break;}memset(vis,0,sizeof(vis));}int rec=0;for(int i=1;i<=n;i++){if(f[i]==i){rec++;}get_num(i,0);}for(int i=1;i<=n;i++){if(num[i]!=v[i].size()+1){flag=false;}}if(rec!=1){flag=false;}if(flag){printf("YES\n");for(int i=1;i<=n;i++){if(f[i]!=i){printf("%d %d\n",f[i],i);}}}else {printf("NO\n");}return 0;
}

View Code

转载于:https://www.cnblogs.com/ZGQblogs/p/10542983.html

Tree Restoration Gym - 101755F (并查集)相关推荐

  1. 2017乌鲁木齐ICPC: I. A Possible Tree(带权并查集)

    I. A Possible Tree Alice knows that Bob has a secret tree (in terms of graph theory) with n nodes wi ...

  2. 牛客多校8 - All-Star Game(线段树分治+并查集按秩合并的撤销操作)

    题目链接:点击查看 题目大意:有 n 个球员和 m 个球迷,一个球员可能是多个球迷的粉丝,需要选择最少的球员进行比赛,使得所有的球迷都愿意观看(对于每个球迷来说,都有至少一个其喜欢的球员入选比赛) 对 ...

  3. 树形结构 —— 并查集

    [概述] 并查集(Union-Find Set)是一种用于分离集合操作的抽象数据类型,其处理的是集合(set)之间的关系,一般处理的是图的连通分量,当给出两个的元素的一个无序对 (a,b) 时,需要快 ...

  4. 【POJ】1308 Is It A Tree?((并查集 + set)or (map))

    http://poj.org/problem?id=1308 这个题数组开到200就可以了,但题目中貌似没有说呢? 读入每一对顶点,看看他们是否在同一个集合中,如果是的话,肯定成环,不是一棵树. 用s ...

  5. HDU 5606 tree 并查集

    tree 把每条边权是1的边断开,发现每个点离他最近的点个数就是他所在的连通块大小. 开一个并查集,每次读到边权是0的边就合并.最后Ans​i​​=size[findset(i)],size表示每个并 ...

  6. HDU 1325 Is It A Tree? 并查集

    点击打开链接 Is It A Tree? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  7. gym:Problem A Artwork(并查集思维题)

    20162017-acmicpc-nordic-collegiate-programming-contest-ncpc-2016 Problem A Artwork 题目链接 http://codef ...

  8. Por Costel and the Match Gym - 100923H(经典种类并查集)

    Por Costel and the Match Gym - 100923H 题目链接:https://vjudge.net/problem/Gym-100923H 题目: Oberyn Martel ...

  9. Gym - 101194G Pandaria (并查集+倍增+线段树合并)

    题意: 给定一个无向图.每个点有一种颜色.现在给定q个询问,每次询问x和w,求所有能通过边权值不超过w的边走到x的点的集合中,哪一种颜色的点出现的次数最多.次数相同时输出编号最小的那个颜色.强制在线. ...

最新文章

  1. 为什么Python没有main函数?
  2. JDK 竟然是这样实现栈的?
  3. gamma校正_什么是Gamma校正?
  4. 【算法】《algorithm-note》算法笔记中文版正式发布!
  5. SecureCRT退出全屏的方法
  6. shell编程详解(一)
  7. composer mysql_php – 无法看到mysql数据库时,composer安装失败
  8. 安卓系统被限制之后,华为手机如何在海外市场销售?
  9. ldap统一用户认证php,针对LDAP服务器进行身份认证
  10. xyz坐标图_“色觉地图”的建立(二):辐照度与亮度、rgb空间、“颜色图”的混色方式...
  11. 消息存储服务器吗,消息服务器 消息存储
  12. C++的使用Lambda
  13. 直方图匹配法(规则化)
  14. 集合数组集合ArrayList
  15. 大麦无线路由器改装打印服务器,大麦domywifi DW33D路由器固件openwrt重分区版
  16. 【洛谷 P3809】 【后缀数组】【模板】后缀排序
  17. 1.CPU基本工作流程
  18. beyond compare文件内容相同依然标红问题+文件过滤
  19. 跳过休息日(周末和节假日)
  20. 【使用python和flask建个人博客】增加了重复类型的卡片功能,用于更好的完成日常的工作与生活

热门文章

  1. ES6学习(五)—数组的扩展
  2. MySQL8.0.25命令行安装与配置
  3. 买房贷款收入证明怎么开?
  4. MacBook Air 是什么意思
  5. 路由器连接久点就慢下来了,怎么回事?
  6. 电视剧《赘婿》宁毅与乌家的岁布战没怎么看懂,可以细致分析一下吗?
  7. 现在企业为何越来越难呢?
  8. “三步走”助你完成领导者转变
  9. 在React和Vue中支持服务器端呈现
  10. python入门——P51模块:模块内测试、搜索路径和包