比赛时候还是太慢了……要是能做快点就能上分了

Monocarp has drawn a tree (an undirected connected acyclic graph) and then has given each vertex an index. All indices are distinct numbers from 11 to nn. For every edge ee of this tree, Monocarp has written two numbers: the maximum indices of the vertices of the two components formed if the edge ee (and only this edge) is erased from the tree.

Monocarp has given you a list of n−1n−1 pairs of numbers. He wants you to provide an example of a tree that will produce the said list if this tree exists. If such tree does not exist, say so.

Input

The first line contains one integer nn (2≤n≤10002≤n≤1000) — the number of vertices in the tree.

Each of the next n−1n−1 lines contains two integers aiai and bibi each (1≤ai<bi≤n1≤ai<bi≤n) — the maximal indices of vertices in the components formed if the ii-th edge is removed.

Output

If there is no such tree that can produce the given list of pairs, print "NO" (without quotes).

Otherwise print "YES" (without quotes) in the first line and the edges of the tree in the next n−1n−1 lines. Each of the last n−1n−1 lines should contain two integers xixi and yiyi (1≤xi,yi≤n1≤xi,yi≤n) — vertices connected by an edge.

Note: The numeration of edges doesn't matter for this task. Your solution will be considered correct if your tree produces the same pairs as given in the input file (possibly reordered). That means that you can print the edges of the tree you reconstructed in any order.


题目大意

现有一棵树。用$n-1$个二元组(x,y)描述树上每条边,表示:删去这条边后,两个连通块内分别最大的编号。

问是否存在一颗符合描述的树。

题目分析

菊花图构造

注意到树被分为两个连通块后,产生的二元组(x,y)中必定有一个元素为$n$.

那么,有多少个二元组$(x,y)(y=n)$就说明有多少条边满足:$[x+1,n]$这些点和$x$点分别在被割断的两块。

树有一个性质:两点间的路径唯一。那么为了割断$x$和$[x+1]...n$,这两个连通块只能有唯一路径,并且路径上的点都必须小于$x$。于是这里有了一种对于单个点$x$的构造方法。那么其他点应该如何考虑?是应该在做出来的路径上分叉还是新开一条?

构造题可以说分为两类:唯一解和多解。这种多解的题,当然选一种最简洁的构造方法。事实上这样对于单点做下去,构造菊花图的方式就是合法的。

我们对于构造菊花图的担忧主要在于,要是每次都新开一条路径,会不会浪费了一些点?换而言之,原先的路径上能不能够共用一些点?

然而,共用路径上的边无论如何只会贡献一种二元组。如果共用,为了达到给定的二元组数量,也只能在原先路径上插上一条可独立的完整路径————也就是说相当于没有共用。

 #include<bits/stdc++.h>
const int maxn = ; int n;
bool used[maxn];
int mp[maxn][maxn];
int edgeTot,edges[maxn<<],nxt[maxn<<],head[maxn]; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
void errorDown()
{
puts("NO");
exit();
}
void addedge(int u, int v)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
}
void dfs(int x, int fa)
{
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (v!=fa) printf("%d %d\n",x,v), dfs(v, x);
}
}
int main()
{
n = read();
memset(head, -, sizeof head);
for (int i=; i<n; i++)
{
int u = read(), v = read();
if (u > v) std::swap(u, v);
if (v!=n) errorDown();
mp[u][v]++;
}
for (int i=; i<n; i++)
if (mp[i][n]){
if (i < mp[i][n]) errorDown();
used[i] = ;
int lst = i, cnt = ;
for (int j=; j<i&&cnt<mp[i][n]-; j++)
if (!used[j]){
used[j] = ;
addedge(lst, j);
lst = j;
cnt++;
}
if (cnt!=mp[i][n]-) errorDown();
addedge(lst, n);
}
puts("YES");
dfs(, );
return ;
}

链构造

上一个做法的最后一段话并不是说不能构造出合法链。事实上可发现,刻意把小的节点接在大节点后也是可以的。

这里介绍一种非常巧妙的链构造:将$a_i$视作前缀最大值,由此构造一条链。

具体的证明和代码见  题解 CF1041E 【Tree Reconstruction】

END

【构造题 贪心】cf1041E. Tree Reconstruction的更多相关文章

  1. [CF1041E]Tree Reconstruction

    题目大意:有一棵树,现在给你每条树边被去掉时,形成的两个联通块中点的最大的编号分别是多少,问满足条件的树存不存在,存在输出方案 题解:一条边的两个编号中较大的一个一定是$n$,否则无解. 开始构造这棵 ...

  2. HDU 5355 Cake (WA后AC代码,具体解析,构造题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5355 题面: Cake Time Limit: 2000/1000 MS (Java/Others) ...

  3. Aizu - 2564 Tree Reconstruction 并查集

    Aizu - 2564 Tree Reconstruction 题意:一个有向图,要使得能确定每一条边的权值,要求是每个点的入权和出权相等,问你最少需要确定多少条边 思路:这题好像有一个定理之类的,对 ...

  4. E. Tree Reconstruction 解析(思維)

    Codeforce 1041 E. Tree Reconstruction 解析(思維) 今天我們來看看CF1041E 題目連結 題目 略,請直接看原題 前言 一開始完全搞錯題目意思,還以為每次會刪除 ...

  5. cf251.2.C (构造题的技巧)

    C. Devu and Partitioning of the Array time limit per test 1 second memory limit per test 256 megabyt ...

  6. hdu4671 Backup Plan ——构造题

    link:http://acm.hdu.edu.cn/showproblem.php?pid=4671 其实是不难的那种构造题,先排第一列,第二列从后往前选. #include <iostrea ...

  7. Educational Codeforces Round 7 D. Optimal Number Permutation 构造题

    D. Optimal Number Permutation 题目连接: http://www.codeforces.com/contest/622/problem/D Description You ...

  8. Codeforces 482 - Diverse Permutation 构造题

    这是一道蛮基础的构造题. - k         +(k - 1)      -(k - 2) 1 + k ,    1 ,         k ,             2,    ....... ...

  9. BZOJ 3097: Hash Killer I【构造题,思维题】

    3097: Hash Killer I Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 963  Solved: 36 ...

随机推荐

  1. 五分钟搞定 Linux 文档全部知识,就看这篇文章

    作者:无痴迷,不成功 来源:见文末 写在前面 我们都知道Linux是一个支持多用户.多任务的系统,这也是它最优秀的特性,即可能同时有很多人都在系统上进行工作,所以千万不要强制关机,同时,为了保护每个人 ...

  2. Python小世界:彻底搞懂Python一切皆对象!!!

    前言 犹记得当初学习Python的时候,对于Python一切皆对象很是懵逼,因为Python是面向对象的动态型语言,而在函数及高阶函数的应用中,如若对于一切皆对象不是有很透彻的了解,基础不是那么牢固的 ...

  3. Nacos深入浅出(八)

    Nacos-spring-context.java 感觉这个后台要比之前的Nacos复杂多了,涉及到很多基础的概念,慢慢看,这个后面慢慢更新解析过程 看到他的目录结构一个是基于注解,一个是XML的解析 ...

  4. CSS样式之操作属性一

    ********css之操作属性******** 一.文本 1.文本颜色:color 颜色属性被用来设置文字的颜色 颜色是通过CSS最经常的指定: 十六进制值 - 如: #FF0000 一个RGB值 ...

  5. Python 工具包 werkzeug 初探

    首先,先向大家介绍一下什么是 werkzeug,Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库.这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架, ...

  6. DNS学习

    DNS (Domain Name System 的缩写)域名系统,万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串.通过域名 ...

  7. 机器学习框架ML.NET学习笔记【5】多元分类之手写数字识别(续)

    一.概述 上一篇文章我们利用ML.NET的多元分类算法实现了一个手写数字识别的例子,这个例子存在一个问题,就是输入的数据是预处理过的,很不直观,这次我们要直接通过图片来进行学习和判断.思路很简单,就是 ...

  8. Jquery3

    动画 动画动画效果一:show(时间),hide(时间)说明:时间的单位为毫秒方法toggle(时间):使用动画切换显示与隐藏动画效果二:slideDown(时间),slideUp(时间)切换:sli ...

  9. IO(File、递归)

      第1章 File 1.1 IO概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了.那怎么办呢?能不能把运算完的数据都保存下来,下 ...

  10. js根据鼠标方向划入遮罩层

    js根据鼠标方向划入遮罩层: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...