• CF 600 D 题解


    CF600D 题解

    题目的字面意思

           给出一个无向图,要求这个图是和谐的,和谐的定义是,如果A 到 C(A  < B  <  C)有一条路, 那么 B 到C也有一条路。数据范围给的是2e5

    然后我们可以意识到,如果一个子集中的所有元素都是连续的,那么这个子集,就是和谐的,因为联通图,任意两点都可以到达。如果说一个子集的元素不是连续的话,那么就一定需要有一条或者多条路径连到别的子集里去。给出两个例子说明:

    然后就变成了怎么处理的问题。

    我使用了并查集,对于相连的点,都合并到小的那个点去,然后更新size数组和maxx数组(size[i]用来记录此时集合i的个数, maxx用来记录集合中的最大值)

    然后我们就可以很愉快的判断,如果maxx[i] – i + 1 == size[i], 那么说明这个集合是和谐的,也就是不需要向外面连边的。

    那么对于不满足条件的一个怎么处理呢?

    很简单遍历i+1到maxx[i], 对需要合并进来的集合进行合并就可以,在这个过程中, maxx[i]是一直在更新的, 所以这个思想的复杂度是O(n), 就很优雅。

     最后放上菜鸟代码

     1 #include <stdio.h>
     2 #include <algorithm>
     3 using namespace std;
     4 const int N = 2e5+10;
     5 int fa[N], maxx[N], size[N];
     6 int find(int x) //并查集基本操作 
     7 {
     8     if(x==fa[x]) return x;
     9     return fa[x] = find(fa[x]);
    10 }
    11 int main()
    12 {
    13     int x, y, fx, fy;
    14     int n, m, res = 0;
    15     scanf("%d %d", &n, &m);
    16     for(int i = 1; i <= n; i++)  //并查集的初始化 
    17     {
    18         fa[i] = i;
    19         maxx[i] = i;
    20         size[i] = 1;
    21     }
    22     for(int i = 1; i <= m; i++)
    23     {
    24         scanf("%d %d", &x, &y);
    25         //判断 然后建里并查集 
    26         fx = find(x); fy = find(y);
    27         if(fx < fy)
    28         {
    29             fa[fy] = fx;
    30             size[fx] += size[fy];
    31             maxx[fx] = max(maxx[fx], maxx[fy]);
    32         }else if(fy < fx){
    33             fa[fx] = fy;
    34             size[fy] += size[fx];
    35             maxx[fy] = max(maxx[fx], maxx[fy]);
    36         }
    37     }
    38     for(int i = 1; i <= n; )
    39     {
    40         if(fa[i]==i) //这个判断没有应该是可以的  
    41         {
    42             //满足条件 
    43             if(size[i]==maxx[i]-i+1) i += size[i];
    44             else{
    45                 // 不满足条件 
    46                 for(int j = i+1; j <= maxx[i]; j++)
    47                 {
    48                     //动态更新 答案++ 
    49                     if(find(j)!=i)
    50                     {
    51                         fa[j] = i;
    52                         size[i] += size[j];
    53                         maxx[i] = max(maxx[i], maxx[j]);
    54                         res++;
    55                     }
    56                 }
    57             }
    58         }
    59     }
    60     printf("%d\n", res);
    61     
    62 }
  • 相关阅读:
    基于C#.NET的Windows进程管理工具
    .NET 中的MD5及hash加密以及密文输出(C#)
    你不一定会的宝宝级数学题
    用C#实现图片文件与base64string编码解码
    怵目惊心的图片
    古鸽和犤毒鸟的故事(扫盲一日)
    office安装问题
    JS 设置与获取Cookie,函数setCookie(name,value,time)getCookie(name)
    JavaScript解码url中的中文字符的方法
    js追加事件FF IE兼容
  • 原文地址:https://www.cnblogs.com/loenvom/p/11876002.html
Copyright © 2020-2023  润新知