HDU1558 - Segment set 并查集 + 判断线段相交

22 篇文章 0 订阅
9 篇文章 0 订阅

HDU1558 - Segment set: http://acm.hdu.edu.cn/showproblem.php?pid=1558

题目大意: 输入一些线段的端点坐标,若两线段相交,则把他们合并成一个集合,输入数据里会有k,问和k线段相交的线段的数目(包括自己)

思路: 每次输入一条线段,都从头扫描一次. 找出之前输入的线段里面,所有和其相交的线段,并且合并(合并用的是线段的ID). 就是: 并查集 + 判断线段相交

代码: 

#include <iostream>
#include <cstring>
#define maxn 1005
using namespace std;
int father[maxn];
struct point{
	double x1,y1,x2,y2;
}p[maxn];//结构体储存线段的两个端点坐标 
bool judge(point x,point y)//利用 叉积 判断线段相交 
{
	double m=(y.x2-y.x1)*(x.y1-y.y1)-(y.y2-y.y1)*(x.x1-y.x1);
	double n=(y.x2-y.x1)*(x.y2-y.y1)-(y.y2-y.y1)*(x.x2-y.x1);
	if(m*n<=0)return true;
	return false;
}
int find(int x)
{
	return x == father[x] ? x : father[x] = find(father[x]); 
}
void join(int x,int y)
{
	x=find(x),y=find(y);
	if(x!=y)
		father[x]=y;
}
int main()
{
	int t,n,k;
	int count,flag;
	char s;
	cin>>t;
	while(t--)
	{
		for(int i=0;i<maxn;i++)father[i]=i;
		cin>>n;
		flag=1;//记录的是线段的数目 
		for(int i=0;i<n;i++)
		{
			cin>>s;
			if(s=='P')
			{
				cin>>p[flag].x1>>p[flag].y1>>p[flag].x2>>p[flag].y2;		
				for(int j=1;j<flag;j++)//每次输入都从头开始扫描之前输入了的线段,判断当前线段是否会和他们相交 
				{
					if(judge(p[flag],p[j])&&judge(p[j],p[flag]))//判断两线段是否相交 
						join(flag,j);//相交则将他们合并 
				}
				flag++;
			}else{
				count=0;
				cin>>k;
				int x=find(k);	
				for(int j=0;j<flag;j++)//计算与k线段是同一集合的线段数目
					if(find(j)==x)count++;
				cout<<count<<endl;
			}
		}
		if(t)cout<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值