hdu 1558 Segment set

简介: 点击打开hdu 1558 思路: 计算几何+并查集 分析: 1 有n个操作,最后求有几个集合或者说是连通分量 2 对于输入一条线段我们就去前面找能够和它相交的线段,利用并查集进行合并并且更新rank数组,rank[x]数组保存的是以x为跟...

点击打开hdu 1558

思路: 计算几何+并查集
分析:
1 有n个操作,最后求有几个集合或者说是连通分量
2 对于输入一条线段我们就去前面找能够和它相交的线段,利用并查集进行合并并且更新rank数组,rank[x]数组保存的是以x为跟节点的集合的线段的数量
3 这一题难点就是线段的相交判断

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const double eps = 1e-8;
const double INF = 1<<30;
const int MAXN = 1010;

struct Node{
    double x1;
    double y1;
    double x2;
    double y2;
};
Node node[MAXN];

int n;
int father[MAXN];
int rank[MAXN];

void init(int m){
    for(int i = 0 ; i <= m ; i++){
        father[i] = i;
        rank[i] = 1;
    }
}

int find(int x){
    if(father[x] != x){
        int fa = father[x];
        father[x] = find(fa);
        rank[x] += rank[fa];
    }
    return father[x];
}

double multiply1(Node a , Node b){
    return (a.x1-a.x2)*(b.y1-a.y1)-(a.y1-a.y2)*(b.x1-a.x1);
}

double multiply2(Node a , Node b){
    return (a.x1-a.x2)*(b.y2-a.y1)-(a.y1-a.y2)*(b.x2-a.x1);
}

bool inter(Node a , Node b){
    if(max(a.x1,a.x2) >= min(b.x1,b.x2) &&
            max(b.x1,b.x2) >= min(a.x1,a.x2) &&
            max(a.y1,a.y2) >= min(b.y1,b.y2) &&
            max(b.y1,b.y2) >= min(a.y1,a.y2) &&
            multiply1(a,b) * multiply2(a,b) <= eps &&
            multiply1(b,a) * multiply2(b,a) <= eps)
        return true;
    else return false;
}
void solve(){
    for(int i = 1 ; i < n ; i++){
        if(inter(node[i] , node[n])){
            int fx = find(i); 
            int fy = find(n);
            if(fx != fy){
                father[fy] = fx;
                rank[fx] += rank[fy];
            }
        }          
    }
}

int main(){
    int cas , m , k;
    bool isFirst = true;
    char c;
    scanf("%d" , &cas);
    while(cas--){
        if(isFirst)
            isFirst = false;
        else
            puts("");
        n = 1;
        scanf("%d%*c" , &m); 
        init(m);
        while(m--){
            c = getchar(); 
            if(c == 'P'){
                scanf("%lf" ,&node[n].x1);       
                scanf("%lf" ,&node[n].y1);       
                scanf("%lf" ,&node[n].x2);       
                scanf("%lf%*c" ,&node[n].y2);       
                if(node[n].x1 > node[n].x2){
                    swap(node[n].x1 , node[n].x2); 
                    swap(node[n].y1 , node[n].y2); 
                }
                solve();
                n++;
            }
            else{
                scanf("%d%*c" , &k); 
                int fa = find(k);
                printf("%d\n" , rank[fa]);
            }
        }
    }
    return 0;
}



目录
相关文章
|
30天前
|
存储 自然语言处理 C++
map和set的简单介绍
map和set的简单介绍
20 1
|
1月前
|
存储 安全 Java
java集合框架及其特点(List、Set、Queue、Map)
java集合框架及其特点(List、Set、Queue、Map)
|
3月前
|
JavaScript 前端开发 定位技术
JavaScript 中如何代理 Set(集合) 和 Map(映射)
JavaScript 中如何代理 Set(集合) 和 Map(映射)
50 0
|
3月前
|
存储 安全 Java
Map和Set(JAVA)
Map和Set(JAVA)
50 1
|
3月前
|
编译器 C++ 容器
【C++学习手札】基于红黑树封装模拟实现map和set
【C++学习手札】基于红黑树封装模拟实现map和set
|
1天前
|
存储 搜索推荐 C++
【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构
【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构
|
21天前
|
存储 JavaScript 前端开发
set和map的区别
set和map的区别
26 4
|
30天前
|
存储 编译器 容器
用红黑树封装实现map和set
用红黑树封装实现map和set
14 0