原题:http://codeforces.com/contest/699/problem/D

题目中所描述的从属关系,可以看作是一个一个块,可以用并查集来维护这个森林。这些从属关系中会有两种环,第一种是一个点从自身出发到自己,这说明该点是一棵子树的根;第二种是从一点出发到另外一个点。这两种情况在并查集合并的时候都会失败,因为合并时他们都已经属于一个子树,我们现在需要做的就是将这些子树合并,这时我们要优先对生成第二种环的子树进行合并,因为这些从属关系一定是需要修改的,第一种情况有一个点可以不需要修改,作为最后合并好的树的根节点。最后,总的操作数等于子树的个数减一,因为最后合并的树的根节点不需要修改。

 #include <bits/stdc++.h>
using namespace std;
const int maxn = ;
int a[maxn];
int f[maxn];//维护并查集
int book[maxn];//标记,为1 的点输出改变后的值,为0输出原值
int find(int x){
if(f[x] == x)
return x;
return f[x] = find(f[x]);
}
int merge(int x,int y){
int u = find(x);
int v = find(y);
if(u != v){
f[v] = u;
return ;
}
return ;
}
int main(){
int n;
scanf("%d",&n);
//并查集初始化
for(int i = ;i<=n;i++){
scanf("%d",&a[i]);
f[i] = i;
}
int cnt = ;//操作计数
int pre = -;//记录需要合并的前一个点
for(int i = ;i<=n;i++){
//对第二种情况的点进行合并
if(!merge(a[i],i) && a[i]!=i){
cnt++;
if(pre != -){
merge(i,pre);
}
pre = i;
book[i] = ;
}
}
//对第一种情况进行合并
for(int i = ;i<=n;i++){
if(i == f[i]){
cnt++;
book[i] = ;
if(pre != -){
merge(i,pre);
}
pre = i;
}
}
printf("%d\n",cnt-);
for(int i = ;i<=n;i++){
if(book[i])
printf("%d ",f[i]);
else
printf("%d ",a[i]);
}
return ;
}

Codeforces 699D Fix a Tree 并查集的更多相关文章

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

    题目链接:http://codeforces.com/contest/699/problem/D D. Fix a Tree time limit per test 2 seconds memory ...

  2. 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 ...

  3. 【并查集】【模拟】Codeforces 698B & 699D Fix a Tree

    题目链接: http://codeforces.com/problemset/problem/698/B http://codeforces.com/problemset/problem/699/D ...

  4. CodeForces 698B Fix a Tree (并查集应用)

    当时也是想到了并查集,但是有几个地方没有想清楚,所以就不知道怎么写了,比如说如何确定最优的问题.赛后看了一下别人的思路,才知道自己确实经验不足,思维也没跟上. 其实没有那么复杂,这个题目我们的操作只有 ...

  5. 【CodeForces】915 F. Imbalance Value of a Tree 并查集

    [题目]F. Imbalance Value of a Tree [题意]给定n个点的带点权树,求所有路径极差的和.n,ai<=10^6 [算法]并查集 [题解]先计算最大值的和,按点权从小到大 ...

  6. Codeforces 731C:Socks(并查集)

    http://codeforces.com/problemset/problem/731/C 题意:有n只袜子,m天,k个颜色,每个袜子有一个颜色,再给出m天,每天有两只袜子,每只袜子可能不同颜色,问 ...

  7. Hdu.1325.Is It A Tree?(并查集)

    Is It A Tree? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  8. Is It A Tree?(并查集)

    Is It A Tree? Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26002   Accepted: 8879 De ...

  9. CF109 C. Lucky Tree 并查集

    Petya loves lucky numbers. We all know that lucky numbers are the positive integers whose decimal re ...

随机推荐

  1. [No000079]罗辑思维2016.1.2日前的所有每日语音,python3做的网络爬虫

    源码地址:https://github.com/charygao/Download_the_LouJiSiWei 写过很久了,vision1.0里有不少bug,今天重新整理修改了一下,运行了一下,2个 ...

  2. 在JS方法中返回多个值的三种方法

    在使用JS编程中,有时需要在一个方法返回两个个或两个以上的数据,用下面的几种方法都可以实现: 1 使用数组的方式,如下: <html> <head> <title> ...

  3. 析构函数virtual与非virtual区别 [转]

    作为通常的原则,如果一个类定义了虚函数,那么它的析构函数就应当是virtual的.因为定义了虚函数则隐含着:这个类会被继承,并且会通过基类的指针指向子类对象,从而得到多态性.   这个类可能会被继承, ...

  4. JavaScript 特殊对象 Array-Like Objects 详解

    这篇文章拖了有两周,今天来跟大家聊聊 JavaScript 中一类特殊的对象 -> Array-Like Objects. (本文节选自 underscore 源码解读系列文章,完整版请关注 h ...

  5. 让JavaScript回归函数式编程的本质

    JavaScript是一门被误会最深的语言,这话一点不假,我们看下它的发展历史. 1995年,Netscape要推向市场,需要一门脚本语言来配套它.是使用一门已有的语言,还是发明一门新的语言,这也不是 ...

  6. RapidJSON 代码剖析(四):优化 Grisu

    我曾经在知乎的一个答案里谈及到 V8 引擎里实现了 Grisu 算法,我先引用该文的内容简单介绍 Grisu.然后,再谈及 RapidJSON 对它做了的几个底层优化. (配图中的<Grisù& ...

  7. Winform开发:在ProgressBar显示百分比数字

    如果不使用Label而是直接在进度条上显示文字,可以扩展一个派生类自己画,代码如下: public partial class Form1 : Form { public Form1() { Init ...

  8. Nginx搭建https服务器

    HTTPS简介 HTTPS(Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单来讲就是HTTP的安全版.即H ...

  9. 利用javascript对字符串加密

    没事利用js写个对字符串加密的方法,基本原理就是先把字符串转化成对应的unicode(用到的方法是charCodeAt()),再把unicode统一减去100(这里加减随便你取多少),把得到的unic ...

  10. 虚拟机VMware 12 Pro 永久许可证激活密钥

    热门虚拟机软件VMware Workstation Pro现已更新至v12.5.2.12.0属于大型更新,专门为Win10的安装和使用做了优化,支持DX10.4K高分辨率显示屏.OpenGL 3.3. ...