2020 BIT冬训-图&&DFS&&BFS K - Harmonious Graph CodeForces - 1253D(并查集)

Problem Description

You're given an undirected graph with n nodes and m edges. Nodes are numbered from 1 to n.

The graph is considered harmonious if and only if the following property holds:

  • For every triple of integers (l,m,r) such that 1l<m<rn, if there exists a path going from node l to node r, then there exists a path going from node l to node m.

In other words, in a harmonious graph, if from a node l we can reach a node r through edges (l<r), then we should able to reach nodes (l+1),(l+2),…,(r−1) too.

What is the minimum number of edges we need to add to make the graph harmonious?

Input

The first line contains two integers nn and mm (3≤n≤200 000 and 1m200 000).

The i-th of the next mm lines contains two integers ui and vi (1ui,vinuivi), that mean that there's an edge between nodes u and v.

It is guaranteed that the given graph is simple (there is no self-loop, and there is at most one edge between every pair of nodes).

Output

Print the minimum number of edges we have to add to the graph to make it harmonious.

Examples

Input
14 8
1 2
2 7
3 4
6 3
5 7
3 8
6 8
11 12
Output
1
Input
200000 3
7 9
9 8
4 5
Output
0

Note

In the first example, the given graph is not harmonious (for instance, 1<6<7, node 1 can reach node 7 through the path 1→2→7, but node 1 can't reach node 6).

However adding the edge (2,4) is sufficient to make it harmonious.

In the second example, the given graph is already harmonious.

这题就得用到并查集了nnd。。

通过并查集。实际上是转换了为跟树差不多的结构。找到该子图中最大的值作为父亲节点。

判断最小值和父亲节点之间的值的父亲节点是否等于最小值的父亲节点。如果不是,则合并,重新选一个最大的更新父亲节点。

AC代码如下:

#include <algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define MAXN 200005
using namespace std;
int n,m,temp1,temp2,fa[MAXN],cnt;
int find(int x){//找到该值对应子图的最大值。
    if(fa[x] == x) 
        return x;
    fa[x]=find(fa[x]);//更新fa【】,便于后面查询 
    return fa[x];    
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=0;i<m;i++){
        scanf("%d%d",&temp1,&temp2);
        temp1=find(temp1); 
        temp2=find(temp2);
        if(temp1>temp2)
            swap(temp1,temp2);//交换 
        fa[temp1]=temp2;//temp1的父亲节点为temp2 
    }
    for(int i=1;i<=n;i++){
        int j=find(i);//i的父亲节点为j 
        while(i<j){//判断i和j之间的数 
            int y = find(i);//y为i和j之间某一点的父亲节点 
            if(j!=y){//如果y和j不同。说明i和该点所在的子图不同。需要连接 
                cnt++;
                if(j<y)
                    swap(j,y);
                fa[y]=j;//将较小的父亲节点的父亲节点设为较大的父亲节点。即可更新全部子节点。 
            }
            i++;
        }
    }
    printf("%d",cnt);
}

 

posted @ 2021-03-04 20:34  mikku  阅读(56)  评论(0)    收藏  举报