[CF1041E]Tree Reconstruction

题目大意:有一棵树,现在给你每条树边被去掉时,形成的两个联通块中点的最大的编号分别是多少,问满足条件的树存不存在,存在输出方案

题解:一条边的两个编号中较大的一个一定是$n$,否则无解。

开始构造这棵树,发现一定可以是一条链,可以钦定$n$在链的一端,把较小值(即前缀$max$)排序,每次变化是就把该位赋成变化值,否则就从前面随便取一个没用过的出来(若没有则无法构造)。

为什么一定可以是链呢?发现无法构造的条件是排序后$i>max_i$,而此时也构造不出树(显然)。

卡点:

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 1010
int n;
int s[maxn], p[maxn];
bool used[maxn];
int main() {
	scanf("%d", &n);
	for (int i = 1, a, b; i < n; i++) {
		scanf("%d%d", &a, &b);
		if (a > b) std::swap(a, b);
		if (b != n) {
			puts("NO");
			return 0;
		}
		s[i] = a;
	}
	std::sort(s + 1, s + n);
	for (int i = 1; i < n; i++) {
		if (s[i] != s[i - 1]) used[p[i] = s[i]] = true;
		else {
			bool found = false;
			for (int j = 1; j < s[i]; j++) if (!used[j]) {
				used[p[i] = j] = found = true;
				break;
			}
			if (!found) {
				puts("NO");
				return 0;
			}
		}
	}
	p[n] = n;
	puts("YES");
	for (int i = 1; i < n; i++) {
		printf("%d %d\n", p[i], p[i + 1]);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/9830504.html

时间: 2024-11-10 14:35:26

[CF1041E]Tree Reconstruction的相关文章

【构造题 贪心】cf1041E. Tree Reconstruction

比赛时候还是太慢了……要是能做快点就能上分了 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 ma

UVA10410 - Tree Reconstruction(队列)

题目:UVA10410 - Tree Reconstruction(队列) 题目大意:给出一棵树的BFS和DFS遍历,求这棵数,如果有多种情况输出一种就可以了. 解题思路:利用BFS将DFS串分段,分成一棵一棵子树.然后将子树用队列存储下来,因为先被分出来的子树,在下一层中也是最先被分段.注意:一定要将根节点分离出去,它不属于它的子树.这棵树不一定是二叉树. 代码: #include <cstdio> #include <queue> #include <vector>

uva 10410 - Tree Reconstruction(栈)

题目链接:uva 10410 - Tree Reconstruction 题目大意:给定一个树的BFS和DFS,求这棵树. 解题思路:用栈维护即可.对应BFS序列映射出了每个节点和根节点的距离,遍历dfs序列,对当前节点和栈顶节点比较,如果该节点距离根节点更远,则说明该节点为栈顶节点个孩子节点,则记录后将节点放入栈中.否则弹掉栈顶元素继续比较.需要注意一点,即当元素与栈顶元素的距离值大1的时候要视为相等,因为它们属于兄弟节点 #include <cstdio> #include <cst

UVA 10410 - Tree Reconstruction(树)

UVA 10410 - Tree Reconstruction 题目链接 题意:给定一个树的dfs序列和bfs序列,求出这颗树 思路:拿dfs的序列,分成若干段,每一段相当一个子树,这样就可以利用bfs的序列去将dfs的序列分段,然后利用一个队列去存放每一段,不断求出子树即可.一开始以为parse tree一定是二叉树,原来不一定啊. 代码: #include <cstdio> #include <cstring> #include <vector> #include

UVA - 10410 Tree Reconstruction

Description You have just finished a compiler design homework question where you had to find the parse tree of an expression. Unfortunately you left your assignment in the library, but luckily your friend picked it up for you. Instead of e-mailing yo

UVA - 10410 Tree Reconstruction (树重建)

题意:给定一个树的bfs和dfs序列,升序输出每个结点的子结点列表. 分析:因为建树不唯一,假定若bfs[u] = bfs[v] + 1,则u是v的兄弟结点,否则是孩子结点.用栈维护. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #in

UVA - 10410 Tree Reconstruction (根据dfs序和bfs序恢复一颗树)

题意: 分析: 这题一开始完全没有思路, 一直没有找出规律. 参考了http://www.cnblogs.com/Wade-/p/6358859.html 和 http://www.cnblogs.com/jerryRey/p/4622927.html 在dfs序列中,相邻的两个结点u,v之间(dfs_pos(u) + 1 =  dfs_pos(v)),有父子,兄弟,其他3种关系. 父子关系:在bfs中u,v并不是相邻, bfs_pos(v) > bfs_pos(u) , 那么u为v父亲, v为

Tree Reconstruction - codeforce

题解:构造策略,将最大值n当作根,其它出现的节点作为叶子节点,然后计算叶子节点出现了几次,则对应这条链上应该有几个节点. int n; int use[1005]; P ans[1004]; int main() { cin >> n; vector<int> a; rep(i, 1, n) { int u, v; cin >> u >> v; if (!use[u]) a.pb(u); use[u]++; use[v]++; } sort(Range(a)

codeforces 1041 E. Tree Reconstruction 和度数有关的构造树

CF 1041E:http://codeforces.com/contest/1041/problem/E 题意: 告诉你一个树的节点个数,显然有n-1条边.已知去掉一条边后,两个集合中最大的节点值.问原来的树形状是怎么样的,构造不出来就输出NO. 思路: 这里说的“度数”可能有点不恰当.指以这个点引出一条链的长度,链上点的值小于这个点. 我想着这应该是可以作为一条链的,但是一直没有想到向节点度数上去想.首先,输入的一对值中,有一个一定是等于n的,那另一个值我们给它度数++.我们把度数为0的点从