Codeforces Round #363 (Div. 2) D. Fix a Tree —— 并查集
题目链接:http://codeforces.com/contest/699/problem/D
2 seconds
256 megabytes
standard input
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:
- There must be exactly one index r that pr = r.
A vertex r is a root of the tree. - 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.
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).
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.
4
2 3 3 4
1
2 3 4 4
5
3 2 2 5 3
0
3 2 2 5 3
8
2 3 5 4 1 6 6 7
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 —— 并查集的更多相关文章
- 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 ...
- 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 ...
- Codeforces Round #363 (Div. 1) B. Fix a Tree 树的拆环
题目链接:http://codeforces.com/problemset/problem/698/B题意:告诉你n个节点当前的父节点,修改最少的点的父节点使之变成一棵有根树.思路:拆环.题解:htt ...
- Codeforces Round #181 (Div. 2) B. Coach 带权并查集
B. Coach 题目连接: http://www.codeforces.com/contest/300/problem/A Description A programming coach has n ...
- Codeforces Round #345 (Div. 1) C. Table Compression dp+并查集
题目链接: http://codeforces.com/problemset/problem/650/C C. Table Compression time limit per test4 secon ...
- 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 ...
- Codeforces Round #375 (Div. 2) D. Lakes in Berland 并查集
http://codeforces.com/contest/723/problem/D 这题是只能把小河填了,题目那里有写,其实如果读懂题这题是挺简单的,预处理出每一块的大小,排好序,从小到大填就行了 ...
- 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 ...
- 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 ...
随机推荐
- upper_bound——自己的实现
int BSearch() { int ln(1),rn(n+1); while(ln+1<rn) { int mid=(ln+rn)>>1; if (Check(mid)) { l ...
- JDK/Java SE官方文档汇总
JDK一般是指Java SE. 1.5:https://docs.oracle.com/javase/1.5.0/docs/ 6:https://docs.oracle.com/javase/6/do ...
- [Bug]由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值"的解决方法(转)
原因 如果使用 Response.End.Response.Redirect 或 Server.Transfer 方法,将出现 ThreadAbortException 异常.您可以使用 try-ca ...
- 织梦dedecms 去掉后台登陆验证码的方法
那么有什么办法解决呢? 那么现在就给大家解决织梦去掉后台登陆验证码. 这里面分两种版本 一个是织梦5.6的程序 那么织梦5.6程序的解决办法是: 在织梦DedeCms5.6版本可以通过下面路径对验 ...
- EasyMvc入门教程-基本控件说明(9)引言导航
休息片刻后,继续开工... 这次我们继续学习引言导航,引言导航主要用于知识点的开始,起到知识点导航的作用.直接例子: 实现代码如下: @Html.Q().BlockRef().Title(" ...
- 使用glReadPixels 读取颜色缓存,深度缓存和模板缓存数据
glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *p ...
- python 工具 图片批量合并
注:代码两处设置 region = (4,3,x-3,y-5) 目的是crop剪去图片的白边,这个可以视情况改变 图片需要命名为 x_1.png .....这样的格式 #encoding=ut ...
- 解决chrome浏览器us-yahoo.com搜索劫持
一直用着greenchrome浏览器,结果有次之后,地址栏的默认搜索引擎用的bing,但是仍然会重定向到us-yahoo.com进行搜索,初起时以为是greenchrome插件作者的返利,类似2345 ...
- 使用Android注解来改善代码
昨晚看到一篇好文章.然后是英文的.所以决定翻译分享给大家.这是原文链接:http://www.michaelevans.org/blog/2015/07/14/improving-your-code- ...
- python(9)- python基础知识刷题
1. 执行 Python 脚本的两种方式 交互方式:命令行 Windows操作系统下,快捷键cmd,输入“python”启动交互式python解释器. 文件方式:python文件 2. 简述位.字 ...