CF698B Fix a Tree 题解 贪心

Fix a Tree

传送门

A tree is an undirected connected graph without cycles.

Let’s consider a rooted undirected tree with n n n vertices, numbered 1 1 1 through n n n . There are many ways to represent such a tree. One way is to create an array with n n n integers p 1 , p 2 , . . . , p n p_{1},p_{2},...,p_{n} p1,p2,...,pn , where p i p_{i} pi denotes a parent of vertex i i i (here, for convenience a root is considered its own parent).

For this rooted tree the array p p p is [ 2 , 3 , 3 , 2 ] [2,3,3,2] [2,3,3,2] .Given a sequence p 1 , p 2 , . . . , p n p_{1},p_{2},...,p_{n} p1,p2,...,pn , one is able to restore a tree:

  1. There must be exactly one index r r r that p r = r p_{r}=r pr=r . A vertex r r r is a root of the tree.
  2. For all other n − 1 n-1 n1 vertices i i i , there is an edge between vertex i i i and vertex p i p_{i} pi .

A sequence p 1 , p 2 , . . . , p n p_{1},p_{2},...,p_{n} p1,p2,...,pn is called valid if the described procedure generates some (any) rooted tree. For example, for n = 3 n=3 n=3 sequences (1,2,2), (2,3,1) and (2,1,3) are not valid.

You are given a sequence a 1 , a 2 , . . . , a n a_{1},a_{2},...,a_{n} a1,a2,...,an , not necessarily valid. Your task is to change the minimum number of elements, in order to get a valid sequence. Print the minimum number of changes and an example of a valid sequence after that number of changes. If there are many valid sequences achievable in the minimum number of changes, print any of them.

Input

The first line of the input contains an integer n n n ( 2 < = n < = 200000 2<=n<=200000 2<=n<=200000 ) — the number of vertices in the tree.

The second line contains n n n integers a 1 , a 2 , . . . , a n a_{1},a_{2},...,a_{n} a1,a2,...,an ( 1 < = a i < = n 1<=a_{i}<=n 1<=ai<=n ).

Output

In the first line print the minimum number of elements to change, in order to get a valid sequence.

In the second line, print any valid sequence possible to get from ( a 1 , a 2 , . . . , a n ) (a_{1},a_{2},...,a_{n}) (a1,a2,...,an) in the minimum number of changes. If there are many such sequences, any of them will be accepted.

Examples

input #1

4
2 3 3 4

output #1

1
2 3 4 4

input #2

5
3 2 2 5 3

output #2

0
3 2 2 5 3

input #3

8
2 3 5 4 1 6 6 7

output #3

2
2 3 7 8 1 6 6 7

Note

In the first sample, it’s enough to change one element. In the provided output, a sequence represents a tree rooted in a vertex 4 4 4 (because p 4 = 4 p_{4}=4 p4=4 ), which you can see on the left drawing below. One of other correct solutions would be a sequence 2 3 3 2, representing a tree rooted in vertex 3 3 3 (right drawing below). On both drawings, roots are painted red.


In the second sample, the given sequence is already valid.

题面翻译

对于下图中的树,

图1

可以用数组表示为 [ 2 , 3 , 3 , 2 ] [2,3,3,2] [2,3,3,2]。这种可以表示树的数组(即有效)需要符合以下条件:

  1. 有且只有一个索引 r r r ,符合 p r = r p_r=r pr=r 。其中顶点 r r r 是树的根。
  2. 对于所有剩下的 n − 1 n-1 n1 个顶点 i i i 一定要有在 i i i p i p_i pi 之间的边。

比如 数列 ( 1 , 2 , 2 ) (1,2,2) (1,2,2) ( 2 , 3 , 1 ) (2,3,1) (2,3,1) ( 2 , 1 , 3 ) (2,1,3) (2,1,3) 都是因为的数目而导致不有效

现在给你一个数组 a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots ,a_n a1,a2,,an不一定有效的。你需要对数组里面的值,通过最小次数更改,使得这个数组有效

并输出最小更改次数和一个通过最小更改次数而更改成功的有效数组

如果有多种解,只需说出任何一组。

输入格式

第一行是一个整数 n ( 2 ≤ n ≤ 200000 ) n\ (2\le n \le 200000) n (2n200000) ----树的顶点个数。

第二行包含 n n n 个整数 a 1 , a 2 , ⋯ , a n ( 1 ≤ a i ≤ n a_1,a_2,\cdots ,a_n\ (1\le a_i\le n a1,a2,,an (1ain

输出格式

第一行一个整数,最小更改次数

第二行输出任意一个通过最小更改次数而更改成功的有效数组。

说明

  • 第一个样例只需要改一个就好啦!第一个样例输出是一个扎根于顶点 4 4 4 的树(因为 p 4 = 4 p_4=4 p4=4),你可以在下面的图中看到。另一个正确的答案应该是数列 2 , 3 , 3 , 2 2,3,3,2 2,3,3,2,扎根在顶点 3 3 3,也可以在下面的图中看到。两个图中顶点将用红色标出。

图2

  • 第二个样例中,给出的数列已经是有效的了。

注明

以上来自 C o d e F o r c e s ,翻译来源:洛谷。 以上来自 CodeForces,翻译来源:洛谷。 以上来自CodeForces,翻译来源:洛谷。

BestMonkey:CodeForces 你什么时候能完善一下你的 Markdown 格式啊!你知道我复制下来题面还要一个一个删多余的空格吗!你看看人家洛谷啊!(愤怒)
CodeForces:我这是为了提高你们的编辑文本效率啊。(叉腰)
BestMonkey:(直接一拳)

解题思路

先考虑确定根节点:

  • 显然,最后只有根节点是自环。所以,若输入中有自环,那就选它为树的总根。显然,答案不会更劣;
  • 如果一开始没有自环,那选择环上一点作为根即可。

然后处理环。用一个数组存下环上节点的颜色。对于每一个节点染色后 DFS(染的颜色要与之前不同),若找到一个节点颜色与当前节点相同,则说明找到了一个环。此时,只要把当前的点指向总根即可。若没有总根,则设置当前节点为总根,再将当前节点的父亲设为自己。

AC Code

#include<bits/stdc++.h>
using namespace std;
char buf[1048576], *p1, *p2;
template<typename T>inline void Super_Quick_Read(T &x) {bool f = 1;x = 0;char ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? 0 : *p1++);while (ch < '0' || ch > '9') {if (ch == '-') f = !f;ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? 0 : *p1++);}while (ch >= '0' && ch <= '9')x = (x << 1) + (x << 3) + (ch ^ 48), ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? 0 : *p1++);x = (f ? x : -x);return;
}
template<typename T>inline void Quick_Write(T x) {if (x < 0) putchar('-'), x = -x;if (x > 9) Quick_Write(x / 10);putchar(x % 10 + '0');return;
}
int n, a[200005];
int Fa[200005], Color[200005], Root, Tag;
inline void DFS(int u) {if (Color[u]) return;Color[u] = Tag;if (Fa[u] == u) {if (!Root) Root = u;else Fa[u] = Root;return;}if (Color[Fa[u]]) {if (Color[Fa[u]] == Tag) if (!Root) Fa[u] = u, Root = Fa[u];else Fa[u] = Root;return;}DFS(Fa[u]);
}
signed main() {Super_Quick_Read(n);for (register int i = 1; i <= n; ++i) Super_Quick_Read(a[i]);memcpy(Fa, a, sizeof(a));for (register int i = 1; i <= n; ++i) if (Fa[i] == i) {Root = i;break;}for (register int i = 1; i <= n; ++i) ++Tag, DFS(i);int count_change = 0;for (register int i = 1; i <= n; ++i) if (Fa[i] != a[i]) ++count_change;Quick_Write(count_change);puts("");for (register int i = 1; i <= n; i++) Quick_Write(Fa[i]), puts(" ");puts("");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/810578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于GitHub的开源讨论系统,赋予网站交互可能

Giscus&#xff1a;让每一条见解直达GitHub&#xff0c;用Giscus开启网站与社区的无缝对话新纪元&#xff01;- 精选真开源&#xff0c;释放新价值。 概览 纯静态网站或博客&#xff0c;由于没有数据存储功能&#xff0c;经常借助第三方的评论系统以插件的方式集成进来&#x…

uniapp 编译后分包下静态图片404问题解决方案

如上图官方说明&#xff1a; 在分包下建立一个static文件夹即可&#xff1a; 分包内代码引用图片 <image src"/分包名称/img/图片名称"></image> <image src"/dataView/img/图片名称"></image>

图书整理 I 1、返回列表 2、头插法,返回链表 3、尾插法,返回链表

返回列表 class Solution:def reverseBookList(self, head: Optional[ListNode]) -> List[int]:li []while head:li.append(head.val)head head.nextreturn li[::-1]头插法&#xff0c;返回链表 class ListNode:def __init__(self, item):self.val itemself.next None…

Rust教程 – 学习天文图像的多尺度处理

最近&#xff0c;人们投入了大量精力开发新颖的图像处理技术。其中许多技术都源自于傅里叶和小波变换等数字信号处理方法。 这些技术不仅使得各种图像处理技术如降噪、锐化和动态范围扩展成为可能&#xff0c;而且还使得计算机视觉中使用的许多技术如边缘检测、目标检测等成为…

RobotFramework测试框架(7)-SeleniumLibrary常用关键字

浏览器操作 打开浏览器 Open Browser urlhttps://www.baidu.com browseredge关闭浏览器 Close Browser最大化浏览器 Maximize Browser Window设置浏览器宽高 Set Window Size 800 600刷新页面 Reload Page iframe操作 选中指定iframe Select Frame loc…

SQL执行流程图文分析:从连接到执行的全貌

SQL执行总流程 下面就是 MySQL 执行一条 SQL 查询语句的流程&#xff0c;也从图中可以看到 MySQL 内部架构里的各个功能模块。 MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层&#xff0c; Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在…

Navicat连接SQL server出现:[IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序(0)

问题 解决方法 一 找到Navicat的安装路径&#xff0c;然后找到sqlncli_x64.msi文件并安装&#xff0c;安装成功后重启Navicat重新进行连接&#xff0c;看是否成功。 解决方法 二 如果方法一没有找到找到sqlncli_x64.msi 还是Navicat的安装路径&#xff0c;然后找到msodbcsql_64…

03-JAVA设计模式-适配器模式

适配器模式 设么是适配器模式 它属于结构型模式&#xff0c;主要用于将一个类的接口转换成客户端所期望的另一种接口&#xff0c;从而使得原本由于接口不兼容而无法协同工作的类能够一起工作。 适配器模式主要解决的是不兼容接口的问题。在软件开发中&#xff0c;经常会有这…

第三十八节 Java 多线程编程

Java 给多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的每一部分都称作一个线程&#xff0c;并且每个线程定义了一个独立的执行路径。 多线程是多任务的一种特别的形式。多线程比多任务需要更小的开销。 这里定义和线程相关的另一个术语&…

信号值解读

dBm&#xff08;分贝毫瓦&#xff09;和RSRP&#xff08;参考信号接收功率&#xff09;都是用于表示无线信号强度的单位&#xff0c;但它们在概念上有所不同。 dBm&#xff1a;dBm是一种表示功率的单位&#xff0c;用于测量无线传输网络中信号的强度&#xff0c;它表示以毫瓦为…

代码随想录算法训练营day38

509. 斐波那契数 五部曲&#xff1a; dp数组下标及含义&#xff1a;dp[i]表示第i个斐波那契数的值dp数组初始化&#xff1a;dp[0]0&#xff0c;dp[1]1递推公式&#xff1a;dp[i] dp[i - 1] dp[i - 2]遍历方向&#xff1a;从前往后dp数组推到举例&#xff1a;0&#xff0c;1…

【错误分享】打开Qt编译生成的软件,“无法找到入口”

错误简介 这张图片显示的是一个计算机错误提示窗口&#xff0c;标题为“无法找到入口”。正文内容是&#xff1a;“无法定位程序输入点_Z21qRegisterResourceDataaiPKhS0_S0_于动态链接库Qt5Core.dll上。” 这意味着在尝试运行程序时遇到了问题。 具体来说&#xff0c;该错误表…

Vue内置组件Transition用法介绍

Vue 提供了两个内置组件&#xff0c;可以帮助你制作基于状态变化的过渡和动画&#xff1a; <Transition> 会在一个元素或组件进入和离开 DOM 时应用动画。本章节会介绍如何使用它。 <TransitionGroup> 会在一个 v-for 列表中的元素或组件被插入&#xff0c;移动&a…

从大量数据到大数据,King’s SDMS仪器数据采集及科学数据管理系统的应用

对于实验室或检测机构&#xff0c;仪器设备是所有业务开展的基础&#xff0c;数据则是核心命脉&#xff0c;而传统的仪器设备原始数据收集方式&#xff0c;效率低耗时长、操作流程不规范、不易保存与查找、错误率高、易篡改等成了制约检测机构持续高速发展的瓶颈和弊端&#xf…

单例19c RMAN数据迁移方案

一、环境说明 源库 目标库 IP 192.168.37.200 192.168.37.202 系统版本 RedHat 7.9 RedHat 7.9 数据库版本 19.3.0.0.0 19.3.0.0.0 SID beg beg hostname beg rman 数据量 1353M 说明:源库已经创建数据库实例&#xff0c;并且存在用户kk和他创建的表空间…

新规来了!智能音视频技术重塑信贷体验

近日&#xff0c;国家金融监督管理总局发布《固定资产贷款管理办法》《流动资金贷款管理办法》《个人贷款管理办法》&#xff08;以下简称“三个办法”&#xff09;。 具体来看&#xff0c;新规明确了以下要求&#xff1a; 1、明确视频面签、电子签约要求 允许商业银行通过视…

Oracle 19c RAC集群相关日志

1.DB日志&#xff08;数据库日志&#xff09; Redo Log&#xff08;重做日志&#xff09;&#xff1a; 在Oracle数据库中&#xff0c;重做日志记录了数据库发生的所有修改操作&#xff0c;包括数据的插入&#xff0c;更新和删除。在RAC的环境中&#xff0c;每个实例都有自己的重…

javascript专题一 ---- 使用不同的方法将小数转换为整数方法总结

在 JavaScript 中&#xff0c;我们经常需要将小数转换为整数。以下是我总结的一些常见的方法&#xff1a; 1、Math.floor(): 这个方法会向下取整&#xff0c;返回小于或等于给定数字的最大整数 var num 3.14; var integerNum Math.floor(num); // integerNum 将会是 3 2、…

Ubuntu22.04搭建CLion C++开发环境

Ubuntu22.04搭建CLion C开发环境 文章目录 Ubuntu22.04搭建CLion C开发环境1.首先下载CLion2.配置c环境3.创建快捷方式Reference 1.首先下载CLion 进入官网https://www.jetbrains.com/clion/download/#sectionlinux 然后进入自己存放这个压缩包的路径中&#xff0c; sudo mkd…

SQLite从出生到现在(发布历史记录)(二十二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;从 SQLite 3.5.9 迁移到 3.6.0&#xff08;二十一&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 引言&#xff1a; SQLite拥有别人无法比拟的装机量&#xff0c;究竟什么成就了SQLite呢&#xff0c;本…