zoukankan      html  css  js  c++  java
  • Codeforces 699D Fix a Tree 并查集

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

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

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 222222;
     4 int a[maxn];
     5 int f[maxn];//维护并查集 
     6 int book[maxn];//标记,为1 的点输出改变后的值,为0输出原值 
     7 int find(int x){
     8     if(f[x] == x)
     9         return x;
    10     return f[x] = find(f[x]);
    11 }
    12 int merge(int x,int y){
    13     int u = find(x);
    14     int v = find(y);
    15     if(u != v){
    16         f[v] = u;
    17         return 1;
    18     }
    19     return 0;
    20 }
    21 int main(){
    22     int n;
    23     scanf("%d",&n);
    24     //并查集初始化 
    25     for(int i = 1;i<=n;i++){
    26         scanf("%d",&a[i]);
    27         f[i] = i; 
    28     }
    29     int cnt = 0;//操作计数 
    30     int pre = -1;//记录需要合并的前一个点 
    31     for(int i = 1;i<=n;i++){
    32         //对第二种情况的点进行合并 
    33         if(!merge(a[i],i) && a[i]!=i){
    34             cnt++;
    35             if(pre != -1){
    36                 merge(i,pre);
    37             }
    38             pre = i;
    39             book[i] = 1;    
    40         }
    41     } 
    42     //对第一种情况进行合并 
    43     for(int i = 1;i<=n;i++){
    44         if(i == f[i]){
    45             cnt++;
    46             book[i] = 1;
    47             if(pre != -1){
    48                 merge(i,pre);
    49             }
    50             pre = i;
    51         } 
    52     }
    53     printf("%d
    ",cnt-1);
    54     for(int i = 1;i<=n;i++){
    55         if(book[i])
    56             printf("%d ",f[i]);
    57         else
    58             printf("%d ",a[i]);
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    将字符串数组转换成整形数组
    层的三级联动
    sql
    工作中的感悟
    asp.net如何抓取其他网站的内容
    看不到的SQl
    对数据库中时间为空的处理和数据转换成百分数
    不带查询条件的分页
    svn中出现红色感叹号
    视图的创建(根据已有的表)
  • 原文地址:https://www.cnblogs.com/zqy123/p/5690790.html
Copyright © 2011-2022 走看看