[hihocoder1490]Tree Restoration恢复树

2023-12-15 23:32

本文主要是介绍[hihocoder1490]Tree Restoration恢复树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题描述

题目2 : Tree Restoration
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
There is a tree of N nodes which are numbered from 1 to N. Unfortunately, its edges are missing so we don’t know how the nodes are connected. Instead we know:

  1. Which nodes are leaves

  2. The distance (number of edges) between any pair of leaves

  3. The depth of every node (the root’s depth is 1)

  4. For the nodes on the same level, their order from left to right

Can you restore the tree’s edges with these information? Note if node u is on the left of node v, u’s parent should not be on the right of v’s parent.

问题描述

输入
The first line contains three integers N, M and K. N is the number of nodes. M is the depth of the tree. K is the number of leaves.

The second line contains M integers A1, A2, … AM. Ai represents the number of nodes of depth i.

Then M lines follow. The ith of the M lines contains Ai numbers which are the nodes of depth i from left to right.

The (M+3)-th line contains K numbers L1, L2, … LK, indicating the leaves.

Then a K × K matrix D follows. Dij represents the distance between Li and Lj.

1 ≤ N ≤ 100

输出
For every node from 1 to N output its parent. Output 0 for the root’s parent.

样例输入
8 3 5
1 3 4
1
2 3 4
5 6 7 8
3 5 6 7 8
0 3 3 3 3
3 0 2 4 4
3 2 0 4 4
3 4 4 0 2
3 4 4 2 0
样例输出
0 1 1 1 2 2 4 4

算法思路

基本的算法就是从下向上,每次处理一层;每层内部的处理是从左到右。
这样就有每次处理的层可以看做最底层,层内每个节点都可以看做叶子节点,而且每个节点都有其与其他叶子节点的距离。每层内部处理的时候交替应用以下规则:
1. 当前层未处理的最左侧节点的父亲节点一定是上一层未处理的且非叶子节点的最左侧节点。
2. 如果两个节点位于同一层且距离为2,那么它们的父亲节点相同。

数据结构

1. 节点

是否是叶子节点+名字+父亲节点的名字

struct Node {
public:bool leaf_flag;int name;int par_name;Node(bool lf=false,int n=-1,int pn = 0):leaf_flag(lf),name(n),par_name(pn) {}Node(const Node& n):leaf_flag(n.leaf_flag),name(n.name),par_name(n.par_name) {}~Node() {}
};

2. 节点集

节点的list。

Node nodes[102];

注意这里就有了对节点的两种索引方式:节点集列表的索引值,节点名称,分别用index/node和name指代,之后的变量命名规则也遵守这个规律。(通常情况下name=index+1,但是为了防止特殊情况,所以使用node2index[]用于两种方式之间的转换)

3. 距离矩阵

存储叶子节点之间的距离,索引值是节点的index。(因为是对称矩阵,实际存储的是个上三角矩阵)
之所以使用一个struct存储距离(而不是直接使用矩阵),就是因为矩阵是对称的,防止信息更新的不及时,或者重复更新。

struct Dist {
public:int dist[101][101];Dist() {}Dist(const Dist& d) {for (int i = 0;i < 101;++i) {for (int j = 0;j < 101;++j)dist[i][j] = d.dist[i][j];}}~Dist() {}int& get(int i,int j) {return dist[min(i,j)][max(i,j)];}
};

代码

1. 变量声明

    Node nodes[102];int name2node[102]={0};int leaves_index[102] = {0};int N,M,K;Dist dist;int m_num[102] = {0},m_sum[102]={0};

2. 数据输入

    cin >> N >> M >> K;for (int i = 0;i < M;++i) {cin >> m_num[i];m_sum[i+1] = m_sum[i]+m_num[i];}for (int i = 0;i < M;++i) {for (int j = 0;j < m_num[i];++j) {cin >> nodes[m_sum[i]+j].name;name2node[nodes[m_sum[i]+j].name] = m_sum[i]+j;}}int tmp_leaf_name=0,tmp_leaf_index=-1;for (int i = 0;i < K;++i) {cin >> tmp_leaf_name;tmp_leaf_index = name2node[tmp_leaf_name];nodes[tmp_leaf_index].leaf_flag = true;leaves_index[i] = tmp_leaf_index;}for (int i = 0;i < K;++i) {tmp_leaf_index = leaves_index[i];for (int j = 0;j < K;++j) {cin >> dist.get(tmp_leaf_index,leaves_index[j]);}}

3. 树结构重构

外层循环是层数循环,从低向上。内层循环是从左到右。

    int cur_index=-1,par_index=-1;//从底向上处理每层for (int m = M-1;m > 0;--m) {//首先处理最左侧的节点cur_index = m_sum[m];par_index = m_sum[m-1];while (cur_index < m_sum[m+1]) {//寻找未处理的非叶子节点的最左侧的上层节点while (nodes[par_index].leaf_flag)++par_index;//应用算法规则1nodes[cur_index].par_name = nodes[par_index].name;//上层的节点就变为新的叶子节点,所以更新其与其他叶子节点的距离(之后只会使用还未处理的叶子节点之间的距离,所以不用在意会出现距离小于0的部分,因为之后不会用到)for (int i = 0;i < N;++i)dist.get(par_index,i) = dist.get(cur_index,i)-1;//从左到右处理++cur_index;++par_index;//应用算法规则2while (cur_index < m_sum[m+1] && dist.get(cur_index-1,cur_index) == 2) {nodes[cur_index].par_name = nodes[cur_index-1].par_name;++cur_index;}}}

4. 信息输出

    for (int i = 1;i <= N;++i)cout << nodes[name2node[i]].par_name << ' ';cout << endl;

5. 全部代码

#include <iostream>
#include <fstream>using namespace std;struct Node {
public:bool leaf_flag;int name;int par_name;Node(bool lf=false,int n=-1,int pn = 0):leaf_flag(lf),name(n),par_name(pn) {}Node(const Node& n):leaf_flag(n.leaf_flag),name(n.name),par_name(n.par_name) {}~Node() {}
};struct Dist {
public:int dist[101][101];Dist() {}Dist(const Dist& d) {for (int i = 0;i < 101;++i) {for (int j = 0;j < 101;++j)dist[i][j] = d.dist[i][j];}}~Dist() {}int& get(int i,int j) {return dist[min(i,j)][max(i,j)];}
};int main()
{
//    freopen("input.txt","r",stdin);Node nodes[102];int name2node[102]={0};int leaves_index[102] = {0};int N,M,K;Dist dist;int m_num[102] = {0},m_sum[102]={0};cin >> N >> M >> K;for (int i = 0;i < M;++i) {cin >> m_num[i];m_sum[i+1] = m_sum[i]+m_num[i];}for (int i = 0;i < M;++i) {for (int j = 0;j < m_num[i];++j) {cin >> nodes[m_sum[i]+j].name;name2node[nodes[m_sum[i]+j].name] = m_sum[i]+j;}}int tmp_leaf_name=0,tmp_leaf_index=-1;for (int i = 0;i < K;++i) {cin >> tmp_leaf_name;tmp_leaf_index = name2node[tmp_leaf_name];nodes[tmp_leaf_index].leaf_flag = true;leaves_index[i] = tmp_leaf_index;}for (int i = 0;i < K;++i) {tmp_leaf_index = leaves_index[i];for (int j = 0;j < K;++j) {cin >> dist.get(tmp_leaf_index,leaves_index[j]);}}int cur_index=-1,par_index=-1;for (int m = M-1;m > 0;--m) {cur_index = m_sum[m];par_index = m_sum[m-1];while (cur_index < m_sum[m+1]) {while (nodes[par_index].leaf_flag)++par_index;nodes[cur_index].par_name = nodes[par_index].name;for (int i = 0;i < N;++i)dist.get(par_index,i) = dist.get(cur_index,i)-1;++cur_index;++par_index;while (cur_index < m_sum[m+1] && dist.get(cur_index-1,cur_index) == 2) {nodes[cur_index].par_name = nodes[cur_index-1].par_name;++cur_index;}}}for (int i = 1;i <= N;++i)cout << nodes[name2node[i]].par_name << ' ';cout << endl;return 0;
}

这篇关于[hihocoder1490]Tree Restoration恢复树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/498299

相关文章

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

树(Tree)——《啊哈!算法》

树 什么是树?树是一种特殊的图,不包含回路的连通无向树。 正因为树有着“不包含回路”这个特点,所以树就被赋予了很多特性。 一棵树中的任意两个结点有且仅有唯一的一条路径连通。一棵树如果有n个结点,那么它一定恰好有n-1条边。在一棵树中加一条边将会构成一个回路。 一棵树有且只有一个根结点。 没有父结点的结点称为根结点(祖先)。没有子结点的结点称为叶结点。如果一个结点既不是根结点也不是叶

如何恢复回收站中已删除/清空的文件

回收站清空后如何恢复已删除的文件?是否可以恢复永久删除的文件?或者最糟糕的是,如果文件直接被删除怎么办?本文将向您展示清空回收站后恢复已删除数据的最佳方法。 回收站清空后如何恢复已删除的文件? “回收站清空后我还能恢复已删除的文件吗?” 答案是肯定的,但是在这种情况下您将需要一个  回收站恢复工具 来从回收站中检索文件: 错误/永久删除回收站或任何数字存储设备中的文件 直接删除的文件/

海鸥相机存储卡格式化如何恢复数据

在摄影的世界里,‌每一张照片都承载着独特的记忆与故事。‌然而,‌当我们不慎将海鸥相机的存储卡格式化后,‌那些珍贵的瞬间似乎瞬间消逝,‌让人心急如焚。‌但请不要绝望,‌数据恢复并非遥不可及。‌本文将详细介绍在海鸥相机存储卡格式化后,‌如何高效地恢复丢失的数据,‌帮助您重新找回那些宝贵的记忆。‌ 图片来源于网络,如有侵权请告知 一、‌回忆备份情况 ‌海鸥相机存储卡格式化如何恢复数据?在意

想要从OPPO手机恢复数据?免费OPPO照片视频恢复软件

此实用程序可帮助那些寻找以下内容的用户: 在OPPO手机中格式化存储卡后可以恢复图片吗?我删除了 OPPO上的视频和图片,我感觉很糟糕,因为里面有我在拉斯维加斯拍摄的视频和照片 免费OPPO照片视频恢复软件 您能恢复OPPO上已删除的照片吗?我不小心格式化了OPPO SD 卡,有希望恢复已删除的照片吗? 救命!我在清理时删除了我的照片,我的问题是是否有任何免费软件可以从OPPO中恢复已

226 Invert Binary Tree

//226 Invert Binary Tree//算法思路:主要使用递归算法public class Solution {public TreeNode invertTree(TreeNode root) {//1 出口 空节点if (root==null)return null;//2 递归 调用自己TreeNode left = root.left;TreeNode right = ro

Oracle Data Guard:Oracle数据库的高可用性和灾难恢复解决方案

在企业级数据库管理中,确保数据的高可用性和在灾难情况下的快速恢复是至关重要的。Oracle Data Guard是Oracle公司提供的一种强大的数据库高可用性解决方案,它通过在主数据库和至少一个备用数据库之间提供实时或近实时的数据保护来实现这一目标。本文将详细介绍如何在Oracle数据库中部署和使用Oracle Data Guard,包括其基本概念、配置步骤、管理技巧和实际应用示例。 1. O

【Redis】Redis Sentinel(哨兵)系统:自动故障恢复与高可用性配置全解

目录 哨兵 (Sentinel)基本概念主从复制的问题⼈⼯恢复主节点故障哨兵⾃动恢复主节点故障 安装部署 (基于 docker)准备⼯作 以下部分是独立于这一章节的Docker安装Server版本安装CentOS安装实战经验 GUI版本安装(以windows 11为例)安装docker 以上部分是独立于这一章节的重新选举redis-master 宕机之后redis-master 重启之

u盘格式化后数据能恢复吗?这四款工具别错过!

作为一个经常需要处理各种数据恢复问题的数码爱好者,我经常被朋友们问到:“如果U盘数据不小心被格式化了,用哪个软件恢复最好?”今天,我就来给大家分享一下我用福昕数据恢复、转转大师数据恢复和超级兔子数据恢复这三款软件恢复格式化U盘数据的实战体验。 首先,我们得知道,数据恢复并不是一件简单的事,尤其是U盘这种便携式存储设备,一旦格式化,数据很容易被覆盖。所以,一旦发现数据丢失,第一时间停止使用U盘,并