题目链接

题意 : 如果两个线段相交就属于同一集合,查询某条线段所属集合有多少线段,输出。

思路 : 先判断与其他线段是否相交,然后合并。

 //
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define eps 1e-8
#define zero(x) (((x) > 0 ? (x) : (-x)) < eps) using namespace std ; struct point
{
double x,y ;
} p[];
struct Line
{
point a;
point b ;
// int num ;
} L[] ;
int father[],numb[],rankk[] ;
int cnt ;
double direction(point p0,point p1,point p2)
{
return (p2.x-p0.x)*(p1.y-p0.y)-(p1.x-p0.x)*(p2.y-p0.y);
} bool on_segment(point p0,point p1,point p2)
{
if((min(p0.x,p1.x)<=p2.x && p2.x<=max(p0.x,p1.x)) && (min(p0.y,p1.y)<=p2.y && p2.y<=max(p0.y,p1.y)))
return true;
return false;
} bool Segment_intersect(point p1,point p2,point p3,point p4)
{
double d1,d2,d3,d4;
d1 = direction(p3,p4,p1);
d2 = direction(p3,p4,p2);
d3 = direction(p1,p2,p3);
d4 = direction(p1,p2,p4);
if(((d1> && d2<)||(d1< && d2>)) && ((d3> && d4<)||(d3<&&d4>)))
return true;
else if((d1== && on_segment(p3,p4,p1)) || (d2== && on_segment(p3,p4,p2)) || (d3== && on_segment(p1,p2,p3)) || (d4== && on_segment(p1,p2,p4)))
return true;
return false;
}
int find_(int x)
{
if(father[x] != x)
father[x] = find_(father[x]) ;
return father[x] ;
} void mergee(int a, int b){
int fx = find_(a);
int fy = find_(b); if (fx != fy){
father[fy] = fx;
numb[fx] += numb[fy];
}
}
void Init()
{
cnt = ;
for(int i=; i<=; i++)
{
numb[i]=;
}
for(int i = ; i < ; i++)
father[i] = i ;
memset(rankk,,sizeof(rankk)) ;
}
int main()
{
int T ,n,ss;
scanf("%d",&T) ;
char s[] ;
while( T--)
{
scanf("%d",&n) ;
Init() ;
for(int i = ; i < n ; i++)
{
scanf("%s",s) ;
if(s[] == 'P')
{
cnt ++ ;
scanf("%lf %lf %lf %lf",&L[cnt].a.x,&L[cnt].a.y,&L[cnt].b.x,&L[cnt].b.y) ;
for(int j = ; j < cnt ; j ++)
if(find_(j) != find_(cnt) && Segment_intersect(L[j].a,L[j].b,L[cnt].a,L[cnt].b))
mergee(j,cnt) ;
}
else
{
scanf("%d",&ss) ;
printf("%d\n",numb[find_(ss)]) ;
}
}
if(T) printf("\n") ;
}
return ;
}

线段非规范相交1

 double cross(point p0,point p1,point p2)
{
return (p2.x-p0.x)*(p1.y-p0.y)-(p1.x-p0.x)*(p2.y-p0.y);
} bool on_segment(point p0,point p1,point p2)
{
if((min(p0.x,p1.x)<=p2.x && p2.x<=max(p0.x,p1.x)) && (min(p0.y,p1.y)<=p2.y && p2.y<=max(p0.y,p1.y)))
return true;
return false;
} bool Segment_intersect(point p1,point p2,point p3,point p4)
{
double d1,d2,d3,d4;
d1 = cross(p3,p4,p1);
d2 = cross(p3,p4,p2);
d3 = cross(p1,p2,p3);
d4 = cross(p1,p2,p4);
if(((d1> && d2<)||(d1< && d2>)) && ((d3> && d4<)||(d3<&&d4>)))
return true;
else if((d1== && on_segment(p3,p4,p1)) || (d2== && on_segment(p3,p4,p2)) || (d3== && on_segment(p1,p2,p3)) || (d4== && on_segment(p1,p2,p4)))
return true;
return false;
}

线段非规范相交2

 double cross(point a, point b, point c)
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
} //aa, bb为一条线段两端点 cc, dd为另一条线段的两端点 相交返回true, 不相交返回false
bool intersect(point aa, point bb, point cc, point dd)
{
if ( max(aa.x, bb.x)<min(cc.x, dd.x) )
{
return false;
}
if ( max(aa.y, bb.y)<min(cc.y, dd.y) )
{
return false;
}
if ( max(cc.x, dd.x)<min(aa.x, bb.x) )
{
return false;
}
if ( max(cc.y, dd.y)<min(aa.y, bb.y) )
{
return false;
}
if ( cross(cc, bb, aa)*cross(bb, dd, aa)< )
{
return false;
}
if ( cross(aa, dd, cc)*cross(dd, bb, cc)< )
{
return false;
}
return true;
}

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

  1. hdu 1558 Segment set (并查集)

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

  2. hdu 1558 Segment set 计算几何+并查集★

    #include <cstdio> #include <iostream> #include <string.h> using namespace std; ; # ...

  3. UVA1455 - Kingdom(并查集 + 线段树)

    UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...

  4. HDU 1811 拓扑排序 并查集

    有n个成绩,给出m个分数间的相对大小关系,问是否合法,矛盾,不完全,其中即矛盾即不完全输出矛盾的. 相对大小的关系可以看成是一个指向的条件,如此一来很容易想到拓扑模型进行拓扑排序,每次检查当前入度为0 ...

  5. hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)

    hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...

  6. 并查集&线段树&树状数组&排序二叉树

    超级无敌巨牛逼并查集(带权并查集)https://vjudge.net/problem/UVALive-4487 带删点的加权并查集 https://vjudge.net/problem/UVA-11 ...

  7. 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)

    题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...

  8. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  9. HDU 1558 Segment set( 判断线段相交 + 并查集 )

    链接:传送门 题意:输入一个数 n 代表有 n 组操作,P 是在平面内加入一条线段,Q x 是查询第 x 条线段所在相交集合的线段个数 例如:下图 5 与 1.2 相交,1 与 3 相交,2 与 4 ...

随机推荐

  1. C# socket 实现消息中心向消息平台 转发消息 (修改)

    using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using ...

  2. iOS学习之Object-C语言内存管理高级

    一.属性的内存管理

  3. 两个有用的shell工具总结

    shell工具之一:sed sed基础 sed编辑器被称作流编辑器,与常见的交互式文本编辑器刚好相反.文本编辑器可以通过键盘来交互式地插入.删除.替换文本中的数据:而流编辑器是基于一组预先的规则来编辑 ...

  4. Linux 编辑器

    vim编辑器 vi作为Unix上的一个编辑器,一直广受欢迎.之后GUN将其移植到开源世界中,经过开发人员对其进行了改善,被称为vi improved,就是现在的vim.为了方便使用,几乎所有的Linu ...

  5. 一样的Android,不一样的学习

    这几年,Android开始慢慢流行起来,很多项目也开始涉及这部分内容,所以学习Android也就变的很有意义了. 学什么 学习Android应该学什么,很多人有不同的见解.一般程序员可能只是学习And ...

  6. Log4j的常见用法

    对于log4j,一般常用的只要保存如下的内容为属性文件即可: #log4j.rootLogger=DEBUG,A1,R log4j.rootLogger=INFO,A1,R log4j.appende ...

  7. 巧用 .NET 中的「合并运算符」获得 URL 中的参数

    获取 URL 中的 GET 参数,无论用什么语言开发网站,几乎是必须会用到的代码.但获取 URL 参数经常需要注意一点就是要先判断是否有这个参数存在,如果存在则取出,如果不存在则用另一个值.这个运算称 ...

  8. jQuery插件开发总结

    jQuery插件的开发包括两种: 一种是类级别的插件开发$.extend,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法,比如:$.ajax, $.getJSON等.jQuery ...

  9. 向Array中添加快速排序

    快速排序思路 1) 假设第一个元素为基准元素 2) 把所有比基准元素小的记录放置在前一部分,把所有比基准元素大的记录放置在后一部分,并把基准元素放在这两部分的中间(i=j的位置) 快速排序实现 Fun ...

  10. Node.js 学习(五)Node.js 事件循环

    Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. Node.j ...