Description:
给定n个开区间,合并他们中的重合者,输出合并后的区间数量。
Input:
第一行:n(1 <= n <= 1000)
第2至第n+1行:每行两个整数,第i行的两个整数表示第i-1个区间的左边界和右边界。
Output:
合并后所剩余的区间数量。
一道经典的并查集问题。
并查集问题讨论关于不相交集合的问题,对于任意两个集合A,B,若有元素x∈A则x∉B,即可以通过集合中任一元素代表该集合。新问题是如何选择代表该集合的元素?代表元素最好能惰性变化。
于是在集合中添加数据结构(即数据间相互关系),由于树有且仅有且必须有一个根节点,于是选择树形结构作为集合内数据逻辑关系模型。
而问题将分为两个子问题:①两线段是否重合,②集合合并问题
①两线段是否重合,纯几何问题,仅提供True或False以标记是否合并
②集合合并,当发现集合A与集合B出现重叠,将二者重合。
#include <stdio.h>
struct NODE{
int left,right;
int father;
}node[1010];
bool Judge(int a, int b){
if(node[b].left >= node[a].right || node[b].right <= node[a].left){
return false;
}
else return true;
}
void Union(int a, int b){
int af = a;
int bf = b;
while(node[af].father != af) af = node[af].father;
while(node[bf].father != bf) bf = node[bf].father;
if(af < bf){
node[bf].father = af;
}
else if(bf < af){
node[af].father = bf;
}
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&node[i].left, &node[i].right);
node[i].father = i;
}
for(int i=0;i<n-1;i++){
for(int k=i+1;k<n;k++){
if(Judge(i,k)){
Union(i,k);
}
}
}
int sum = 0;
for(int i=0;i<n;i++){
if(node[i].father == i) sum++;
}
printf("%d\n",sum);
return 0;
}