**链接:****传送门 **

题意:输入一个数 n 代表有 n 组操作,P 是在平面内加入一条线段,Q x 是查询第 x 条线段所在相交集合的线段个数

  • 例如:下图 5 与 1、2 相交,1 与 3 相交,2 与 4 相交,所以这个相交集合的线段为 1、2、3、4、5,所以 Q 5 答案为 5

思路:

  1. 可以使用并查积来描述“相交集合”,如果两个线段相交,就 unite 这两个线段所在集合,需要注意的是,在进行 unite 的时候,需要对两个集合中所有元素进行处理

  2. 如何查询每个集合中线段的个数?题目给的数据量较小,可以直接扫描整个 par[] 数组来记录个数

balabala:下面两种做法再次体现了知识面的决定性作用TAT!方法1——46 Ms AC ,方法2——156 Ms AC!接近4倍的时间!


方法1:加一个数组维护集合中线段的个数,这个想法来源于这一道题 ---> 戳这里!

/*************************************************************************
> File Name: hdu1558t2.cpp
> Author: WArobot
> Blog: http://www.cnblogs.com/WArobot/
> Created Time: 2017年05月08日 星期一 19时38分36秒
************************************************************************/ #include<bits/stdc++.h>
using namespace std; #define eps 1e-10
const int maxn = 1010;
struct point{ double x,y; };
struct V{ point s,e; };
int par[maxn] , num[maxn]; // 线段相交部分
bool inter(point a,point b,point c,point d){
if( min(a.x,b.x) > max(c.x,d.x) ||
min(a.y,b.y) > max(c.y,d.y) ||
min(c.x,d.x) > max(a.x,b.x) ||
min(c.y,d.y) > max(a.y,b.y)
)return 0;
double h,i,j,k;
h = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
i = (b.x-a.x)*(d.y-a.y) - (b.y-a.y)*(d.x-a.x);
j = (d.x-c.x)*(a.y-c.y) - (d.y-c.y)*(a.x-c.x);
k = (d.x-c.x)*(b.y-c.y) - (d.y-c.y)*(b.x-c.x);
return h*i<=eps && j*k<=eps;
}
// 并查集部分
void init(){
for(int i=0;i<maxn;i++){
par[i] = i;
num[i] = 1;
}
}
int find(int x){
if(par[x] == x) return x;
else return par[x] = find(par[x]);
}
void unite(int x,int y){
x = find(x);
y = find(y);
if(x==y) return;
else{
par[y] = x;
num[x] += num[y]; // 在合并的同时维护集合数目
}
} void solve(int k,int x){
int fx = find(x);
unite( k , x );
/*for(int i = 0 ; i < k ; i++){
if( par[i] == fx ) par[i] = k;
}*/
}
int main(){
int T , N , x , k , kase = 0;;
string op;
V v[maxn];
scanf("%d",&T);
while(T--){
if( kase > 0 ) printf("\n");
kase++; init(); // 初始化并查集 scanf("%d",&N);
k = 0;
while(N--){
cin>>op;
if( op == "P" ){
scanf("%lf%lf%lf%lf", &v[k].s.x , &v[k].s.y , &v[k].e.x , &v[k].e.y );
for(int i = 0 ; i < k ; i++){
if( inter(v[k].s,v[k].e,v[i].s,v[i].e) )
solve( k , i );
}
k++;
}
else{
scanf("%d",&x); x -= 1;
/*int cnt = 0;
for(int i = 0 ; i <= k ; i++){
if( par[i] == par[x] ) cnt++;
}
printf("%d\n",cnt);*/
printf("%d\n", num[ find(x) ] );
}
}
/*for(int i = 0 ; i < k ; i++){
printf("i = %d , par[i] = %d\n",i,par[i]);
}*/
}
return 0;
}

方法2:非常非常蠢的写法

/*************************************************************************
> File Name: hdu1558.cpp
> Author: WArobot
> Blog: http://www.cnblogs.com/WArobot/
> Created Time: 2017年05月08日 星期一 00时00分36秒
************************************************************************/ #include<bits/stdc++.h>
using namespace std; #define eps 1e-10
const int maxn = 1010;
struct point{ double x,y; };
struct V{ point s,e; };
int par[maxn]; // 线段相交部分
bool inter(point a,point b,point c,point d){
if( min(a.x,b.x) > max(c.x,d.x) ||
min(a.y,b.y) > max(c.y,d.y) ||
min(c.x,d.x) > max(a.x,b.x) ||
min(c.y,d.y) > max(a.y,b.y)
)return 0;
double h,i,j,k;
h = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
i = (b.x-a.x)*(d.y-a.y) - (b.y-a.y)*(d.x-a.x);
j = (d.x-c.x)*(a.y-c.y) - (d.y-c.y)*(a.x-c.x);
k = (d.x-c.x)*(b.y-c.y) - (d.y-c.y)*(b.x-c.x);
return h*i<=eps && j*k<=eps;
}
// 并查集部分
void init(){
for(int i=0;i<maxn;i++){
par[i] = i;
}
}
int find(int x){
if(par[x] == x) return x;
else return par[x] = find(par[x]);
}
void unite(int x,int y){
x = find(x);
y = find(y);
if(x==y) return;
else par[y] = x;
} void solve(int k,int x){
int fx = find(x); // 先找到 x 的祖先再合并 x,否则合并之后就无法处理原本 x 所在集合的所有元素了
unite( k , x );
for(int i = 0 ; i < k ; i++){
if( par[i] == fx ) par[i] = k;
}
}
int main(){
int T , N , x , k , kase = 0;;
string op;
V v[maxn];
scanf("%d",&T);
while(T--){
if( kase > 0 ) printf("\n");
kase++; init(); // 初始化并查集 scanf("%d",&N);
k = 0;
while(N--){
cin>>op;
if( op == "P" ){
scanf("%lf%lf%lf%lf", &v[k].s.x , &v[k].s.y , &v[k].e.x , &v[k].e.y );
for(int i = 0 ; i < k ; i++){
if( inter(v[k].s,v[k].e,v[i].s,v[i].e) )
solve( k , i );
}
k++;
}
else{
scanf("%d",&x); x -= 1;
int cnt = 0;
for(int i = 0 ; i <= k ; i++){
if( par[i] == par[x] ) cnt++;
}
printf("%d\n",cnt);
}
}
/*for(int i = 0 ; i < k ; i++){
printf("i = %d , par[i] = %d\n",i,par[i]);
}*/
}
return 0;
}

HDU 1558 Segment set( 判断线段相交 + 并查集 )的更多相关文章

  1. poj 1127:Jack Straws(判断两线段相交 + 并查集)

    Jack Straws Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2911   Accepted: 1322 Descr ...

  2. hdu 1558 线段相交+并查集

    题意:要求相交的线段都要塞进同一个集合里 sol:并查集+判断线段相交即可.n很小所以n^2就可以水过 #include <iostream> #include <cmath> ...

  3. 判断线段相交(hdu1558 Segment set 线段相交+并查集)

    先说一下题目大意:给定一些线段,这些线段顺序编号,这时候如果两条线段相交,则把他们加入到一个集合中,问给定一个线段序号,求在此集合中有多少条线段. 这个题的难度在于怎么判断线段相交,判断玩相交之后就是 ...

  4. TTTTTTTTTTTTTT poj 1127 Jack Straws 线段相交+并查集

    题意: 有n个木棍,给出木棍的两个端点的x,y坐标,判断其中某两个线段是否连通(可通过其他线段连通) #include <iostream> #include <cstdio> ...

  5. hdu 1558 (线段相交+并查集) Segment set

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐 ...

  6. hdu 1558 线段相交+并查集路径压缩

    Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)

    Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped ...

  8. [poj 1127]Jack Straws[线段相交][并查集]

    题意: 给出一系列线段,判断某两个线段是否连通. 思路: 根据线段相交情况建立并查集, 在同一并查集中则连通. (第一反应是强连通分量...实际上只要判断共存即可, 具体的方向啊是没有关系的..) 并 ...

  9. poj1127 Jack Straws(线段相交+并查集)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Jack Straws Time Limit: 1000MS   Memory L ...

随机推荐

  1. 【CF666E】Forensic Examination - 广义后缀自动机+线段树合并

    广义SAM专题的最后一题了……呼 题意: 给出一个长度为$n$的串$S$和$m$个串$T_{1\cdots m}$,给出$q$个询问$l,r,pl,pr$,询问$S[pl\cdots pr]$在$T_ ...

  2. Blender软件导出的obj数据格式文件内容解读

    [cube.obj] # Blender v2.78 (sub 0) OBJ File: '' # www.blender.org mtllib cube.mtl #这里是引用了一个外部材质文件cub ...

  3. 最长上升子序列(LIS)与最长公共子序列(LCS)

    1.LIS : 给定一个序列,求它的最长上升子序列(n<=2000) 第一种 O(n^2): dp[i] 为以i为开头的最长上升子序列长度 code1: #include<cstdio&g ...

  4. Python智能提示--提示对象内涵成员

    1. demo展示 2. 提示效果

  5. JS三角形

    1.直角三角形 <script> ; ; i++) { //外层循环代表的是要循环的行数 ; j < i; j++) { //内层循环代表的是要打印的列数 document.writ ...

  6. Inflation System Properties

    https://blogs.oracle.com/buck/inflation-system-properties I wanted to write a quick post about the t ...

  7. HDU 2817 EASY题

    #include <iostream> #include <cstdio> using namespace std; const __int64 MOD=200907; __i ...

  8. MacBook Pro安装Photoshop且支持Retina有你们说的那么困难吗!

    直接看效果图! 超清晰吧...... 在此之前我也是网罗各种方法,各种步骤,各种琳琅满目.并且也没效果,要么是破解成功,要么是不支持Retina.这不瞎折腾嘛! 想起我在windows上的方法,认为在 ...

  9. 从头认识java-13.5 利用泛型构建复杂模型

    这一章节我们来展示一下如何利用泛型构建复杂模型? 1.元组列表 我们之前已经说过元组是一个复杂的模型,能够返回多对象. package com.ray.ch11; import java.util.A ...

  10. jQuery插件 -- Cookie插件

    Cookie是站点设计者放置在client的小文本文件.Cookie能为用户提供非常多的使得,比如购物站点存储用户以前浏览过的产品列表.或者门户站点记住用户喜欢选择浏览哪类新闻. 在用户同意的情况下. ...