0
点赞
收藏
分享

微信扫一扫

并查集+计算几何线段相交(快速排斥实验&跨立实验) HDU 1558 Segment set

数数扁桃 2023-02-07 阅读 100


Segment set

TimeLimit: 3000/1000 MS (Java/Others)    Memory Limit:32768/32768 K (Java/Others)
Total Submission(s): 5359    Accepted Submission(s): 2064

ProblemDescription

A segmentand all segments which are connected with it compose a segment set. The size ofa segment set is the number of segments in it. The problem is to find the sizeof some segment set.

 

 

Input

In the first line there is an integer t -the number of test case. For each test case in first line there is an integer n(n<=1000) - the number of commands.

There are two different commands described in different format shown below:

P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are(x1,y1),(x2,y2).
Q k - query the size of the segment set which contains the k-th segment.

k is between 1 and the number of segments in the moment. There is no segment inthe plane at first, so the first command is always a P-command.

并查集+计算几何线段相交(快速排斥实验&跨立实验)  HDU  1558 Segment set_d3

 

 

Output

For each Q-command, output the answer.There is a blank line between test cases.

 

 

SampleInput

1

10

P 1.001.00 4.00 2.00

P 1.00-2.00 8.00 4.00

Q 1

P 2.003.00 3.00 1.00

Q 1

Q 3

P 1.004.00 8.00 2.00

Q 2

P 3.003.00 6.00 -2.00

Q 5

 

 

SampleOutput

1

2

2

2

5

 

 

Author

LL

 

 

Source

​​HDU2006-12 Programming Contest ​​

 

 

Recommend

LL

 

LL 

算法分析:

题意:给几条线段,动态输出条线段所在的集合中包含的线段的个数

算法:并查集+快速排斥实验&跨立实验​​(点这里)​​ 判断两直线是否相交(相交合并即可)

代码实现:

#include<bits/stdc++.h>
using namespace std;;
#define N 1005
int fa[N],num[N];
int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
struct point{
double x,y;
}P1,P2,Q1,Q2;
struct Edge
{
point a,b;
}e[N];
double xmult(point a,point b,point c) //大于零代表a,b,c左转
{
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
bool OnSegment(point a,point b,point c) //a,b,c共线时有效
{
return c.x>=min(a.x,b.x)&&c.x<=max(a.x,b.x)&&c.y>=min(a.y,b.y)&&c.y<=max(a.y,b.y);
}

bool Cross(point a,point b,point c,point d) //判断ab 与cd是否相交
{
double d1,d2,d3,d4;
d1=xmult(c,d,a);
d2=xmult(c,d,b);
d3=xmult(a,b,c);
d4=xmult(a,b,d);
if(d1*d2<0&&d3*d4<0) return 1;
else if(d1==0&&OnSegment(c,d,a)) return 1;
else if(d2==0&&OnSegment(c,d,b)) return 1;
else if(d3==0&&OnSegment(a,b,c)) return 1;
else if(d4==0&&OnSegment(a,b,d)) return 1;
return 0;
}
int main()
{

int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
num[i]=1;fa[i]=i;
}
int sum=0;
char s[5];
for(int i=1;i<=n;i++)
{
scanf("%s",s);
if(s[0]=='P')
{
sum++;
scanf("%lf%lf%lf%lf",&e[sum].a.x,&e[sum].a.y,&e[sum].b.x,&e[sum].b.y);
for(int j=1;j<sum;j++)
{
if(find(j)!=find(sum)&&Cross(e[sum].a,e[sum].b,e[j].a,e[j].b))
{
//cout<<sum<<" "<<j<<endl;
int r1=find(sum),r2=find(j);
if(r1!=r2)
{
//cout<<r1<<" "<<r2<<endl;
fa[r1]=r2;
num[r2]+=num[r1];//注意r2才是父亲节点

}
}

}
}
else
{
int t;
scanf("%d",&t);
printf("%d\n",num[find(t)]);//找他的父亲节点的集合线段数
}
}
if(T)//每个测试用例要输出空行,注意最后一个样例不用输出空行
printf("\n");
}
return 0;

}


举报

相关推荐

0 条评论