题目链接:http://codeforces.com/contest/699/problem/D

D. Fix a Tree
time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

A tree is an undirected connected graph without cycles.

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

For
this rooted tree the array p is [2, 3, 3, 2].

Given a sequence p1, p2, ..., pn,
one is able to restore a tree:

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

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

You are given a sequence 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 (2 ≤ n ≤ 200 000) —
the number of vertices in the tree.

The second line contains n integers a1, a2, ..., an (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 (a1, a2, ..., an) in
the minimum number of changes. If there are many such sequences, any of them will be accepted.

Examples
input
4
2 3 3 4
output
1
2 3 4 4
input
5
3 2 2 5 3
output
0
3 2 2 5 3
input
8
2 3 5 4 1 6 6 7
output
2
2 3 7 8 1 6 6 7

题意:

有n个节点,给出每个点的父节点。问至少修改多少个节点的父节点,使得这些节点刚好构成一棵树?

题解:

1.经过分析,假设在初始状态有k个集合,那么对于每一个集合,它要么是一棵根节点的父节点为自己的树,要么是一棵根节点的父节点为其子孙的树(虽然不是树,但姑且这么叫,便于理解)。

2.首先用并查集使得每个集合“现出原形”,得到集合后,需要选一个根节点,作为最终树的根节点,父节点为自己的根节点优先被选择,然后再把其他根节点的 父节点改为最终树的根节点。如果选另一种,就需要把它的父节点改为自己,真正作为根节点(这个集合就真真正正是一棵树了)后,再把其他根节点的父节点改为最终树的根节点,这样就多了一次修改。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <algorithm>
using namespace std;
#define ms(a, b) memset((a), (b), sizeof(a))
typedef long long LL;
const double eps = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int maxn = +; int fa[maxn], a[maxn], b[maxn];
int n; int find(int x) { return fa[x]==x? fa[x]=x:find(fa[x]); } void init()
{
scanf("%d",&n);
for(int i = ; i<=n; i++)
scanf("%d",&a[i]), b[i] = a[i], fa[i] = i;
} void solve()
{
for(int i = ; i<=n; i++)
{
int u = a[i], v = i;
int m1 = find(u);
int m2 = find(v); if(m1!=m2)
fa[m2] = m1;
} int rt = ;
for(int i = ; i<=n; i++)
if(fa[i]==i && a[i]==i)
{
rt = i;
break;
} for(int i = ; i<=n; i++)
{
if(fa[i]==i)
{
if(!rt)
rt = i, a[i] = i;
else
a[i] = rt;
}
} int ans = ;
for(int i = ; i<=n; i++)
if(a[i]!=b[i])
ans++; printf("%d\n",ans);
for(int i = ; i<=n; i++)
printf("%d ",a[i]);
} int main()
{
// int T;
// scanf("%d",&T);
// while(T--)
{
init();
solve();
}
return ;
}

Codeforces Round #363 (Div. 2) D. Fix a Tree —— 并查集的更多相关文章

  1. Codeforces Round #363 (Div. 2)D. Fix a Tree(并查集)

    D. Fix a Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  2. Codeforces Round #363 (Div. 2) 698B Fix a Tree

    D. Fix a Tree time limit per test 2 seconds memory limit per test 256 megabytes     A tree is an und ...

  3. Codeforces Round #363 (Div. 1) B. Fix a Tree 树的拆环

    题目链接:http://codeforces.com/problemset/problem/698/B题意:告诉你n个节点当前的父节点,修改最少的点的父节点使之变成一棵有根树.思路:拆环.题解:htt ...

  4. Codeforces Round #181 (Div. 2) B. Coach 带权并查集

    B. Coach 题目连接: http://www.codeforces.com/contest/300/problem/A Description A programming coach has n ...

  5. Codeforces Round #345 (Div. 1) C. Table Compression dp+并查集

    题目链接: http://codeforces.com/problemset/problem/650/C C. Table Compression time limit per test4 secon ...

  6. Codeforces Round #346 (Div. 2) F. Polycarp and Hay 并查集 bfs

    F. Polycarp and Hay 题目连接: http://www.codeforces.com/contest/659/problem/F Description The farmer Pol ...

  7. Codeforces Round #375 (Div. 2) D. Lakes in Berland 并查集

    http://codeforces.com/contest/723/problem/D 这题是只能把小河填了,题目那里有写,其实如果读懂题这题是挺简单的,预处理出每一块的大小,排好序,从小到大填就行了 ...

  8. Codeforces Round #603 (Div. 2) D. Secret Passwords(并查集)

    链接: https://codeforces.com/contest/1263/problem/D 题意: One unknown hacker wants to get the admin's pa ...

  9. Codeforces Round #360 (Div. 1) D. Dividing Kingdom II 并查集求奇偶元环

    D. Dividing Kingdom II   Long time ago, there was a great kingdom and it was being ruled by The Grea ...

随机推荐

  1. codevs——1008 选数

    1008 选数 2002年NOIP全国联赛普及组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 已知 n ...

  2. javascript --- 多重继承

    多重继承就是指,一个子对象中有不止一个父对象的继承模式. 想要实现她,还是非常简单的,而我们只需要延续属性拷贝的继承思路依次扩展对象即可,而对参数中所继承的对象没有限制. function multi ...

  3. Oracle SOA Suite OverView

    SOA是一场架构的变革,那既然是变革,那就一定是有内在的原因来推动这个架构的变革.在过去几十年的时间里面,应用程序架构已经经历了3次巨大的变革,从Terminal/主机--> Client/Se ...

  4. 【redis】5.spring boot项目中,直接在spring data jpa的Repository层使用redis +redis注解@Cacheable直接在Repository层使用,报错问题处理Null key returned for cache operation

    spring boot整合redis:http://www.cnblogs.com/sxdcgaq8080/p/8028970.html 首先,明确一下问题的场景 之前在spring boot整合re ...

  5. Ubuntu -- 下如何查看CPU信息, 包括位数和多核信息

    from: http://hi.baidu.com/sdusoul/blog/item/76f349508f74fb6e843524eb.html 查看当前操作系统内核信息# uname -a Lin ...

  6. awk如何区分shell脚本传进来的参数和自身的参数?awk如何获取shell脚本传进来的参数;awk中如何执行shell命令

    问题:对于shell脚本,$0表示脚本本身,$1表示脚本的第一个参数,$2……依次类推:对于awk,$1表示分割后的第一个字段,$2……依次类推.那么对于shell脚本中的awk如何区分两者呢? 答案 ...

  7. Android学习笔记(35):Android活动条

    在Android3.0之后,Google对UI导航设计上进行了一系列的改革,当中有一个很好用的新功能就是引入的ActionBar,用于代替3.0之前的标题栏,并提供更为丰富的导航效果. ActionB ...

  8. Git 的使用Git Bash和Git GUI

    使用Github也有一年的时间了,之前一直都是使用的Github客户端,对提交,更新,克隆,合并,分支有一定的了解和实践.一直都想试试命令行的形式,但是感觉可能桌面版的方便就没有做. 可是Github ...

  9. C#中如何让ListView控件点击选中整行

    将Listview控件的FullRowSelect属性置为True,当然Listview的View属性应该是Details. 2017年6月25日17:15:55

  10. EasyUI datagrid border处理,加边框,去边框,都可以,easyuidatagrid

    下面是EasyUI 官网上处理datagrid border的demo: 主要是这句: $('#dg').datagrid('getPanel').removeClass('lines-both li ...