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 }

 

 

 

 

 

 

 

 

posted @ 2019-11-17 12:45  loenvom  阅读(169)  评论(0编辑  收藏  举报