HDU 1558 Segment set( 判断线段相交 + 并查集 )
**链接:****传送门 **
题意:输入一个数 n 代表有 n 组操作,P 是在平面内加入一条线段,Q x 是查询第 x 条线段所在相交集合的线段个数
- 例如:下图 5 与 1、2 相交,1 与 3 相交,2 与 4 相交,所以这个相交集合的线段为 1、2、3、4、5,所以 Q 5 答案为 5

思路:
可以使用并查积来描述“相交集合”,如果两个线段相交,就 unite 这两个线段所在集合,需要注意的是,在进行 unite 的时候,需要对两个集合中所有元素进行处理
如何查询每个集合中线段的个数?题目给的数据量较小,可以直接扫描整个 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( 判断线段相交 + 并查集 )的更多相关文章
- poj 1127:Jack Straws(判断两线段相交 + 并查集)
Jack Straws Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2911 Accepted: 1322 Descr ...
- hdu 1558 线段相交+并查集
题意:要求相交的线段都要塞进同一个集合里 sol:并查集+判断线段相交即可.n很小所以n^2就可以水过 #include <iostream> #include <cmath> ...
- 判断线段相交(hdu1558 Segment set 线段相交+并查集)
先说一下题目大意:给定一些线段,这些线段顺序编号,这时候如果两条线段相交,则把他们加入到一个集合中,问给定一个线段序号,求在此集合中有多少条线段. 这个题的难度在于怎么判断线段相交,判断玩相交之后就是 ...
- TTTTTTTTTTTTTT poj 1127 Jack Straws 线段相交+并查集
题意: 有n个木棍,给出木棍的两个端点的x,y坐标,判断其中某两个线段是否连通(可通过其他线段连通) #include <iostream> #include <cstdio> ...
- hdu 1558 (线段相交+并查集) Segment set
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐 ...
- hdu 1558 线段相交+并查集路径压缩
Segment set Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)
Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped ...
- [poj 1127]Jack Straws[线段相交][并查集]
题意: 给出一系列线段,判断某两个线段是否连通. 思路: 根据线段相交情况建立并查集, 在同一并查集中则连通. (第一反应是强连通分量...实际上只要判断共存即可, 具体的方向啊是没有关系的..) 并 ...
- poj1127 Jack Straws(线段相交+并查集)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Jack Straws Time Limit: 1000MS Memory L ...
随机推荐
- ajax异步上传文件和表单同步上传文件 的区别
1. 用表单上传文件(以照片为例)-同步上传 html部分代码:这里请求地址index.php <!DOCTYPE html> <html lang="en"&g ...
- mysql数据库增量恢复
mysqldump -uroot -p -B discuzx -F -x --master-data=2 --events|gzip >/root/discuzx.sql.gz 写入数据 删除数 ...
- Nginx 安装配置证书,设置HTTPS站点
详细配置如下: server { listen 80; server_name shwww.net www.shwww.net; return 301 https://www.shwww.net$re ...
- 为DK2应用程序迁移到Oculus CV1做好准备!
为DK2应用程序迁移到Oculus CV1做好准备! 本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/arti ...
- 导出MNIST的数据集
在TensorFlow的官方入门课程中,多次用到mnist数据集. mnist数据集是一个数字手写体图片库,但它的存储格式并非常见的图片格式,所有的图片都集中保存在四个扩展名为idx3-ubyte的二 ...
- 完整的html+css+javascript实现跟随鼠标移动显示选中效果
1,显示效果: 2,html结构 <div class="process_list-lpu"> <div class="process_line&quo ...
- HDU 2035 不忍直视的水
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; in ...
- POJ--2112--Optimal Milking【Floyd+Dinic+二分答案】
链接:http://poj.org/problem?id=2112 题意:有k个挤奶器.编号1~k,c头牛,编号k+1~k+c,每一个挤奶器最多能给m头牛挤奶,给你一个k+c的邻接矩阵.要求每头牛都能 ...
- node 上传文件 http client to post file
node做http client 发送post数据是很容易的事情,但要上传文件就不是太容易了主要是因为上传文件的报文和普通post是不太一样的 要了解http post可以看下这个 https://i ...
- 【Cocos2d-x】坐标系和图层
在Cocos2D-X中,存在四种坐标系: 1.OpenGL坐标系:该坐标系原点在屏幕左下角.x轴向右,y轴向上.这也就是cocos2dx中用到的坐标系所以没啥好说的. 2.屏幕坐标系(UIKit坐标) ...