码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-08-26 22:32:23      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:hdu   数据结构   并查集   判断线段相交   

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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:hdu   数据结构   并查集   判断线段相交   

原文地址:http://blog.csdn.net/p_rogrammer/article/details/48009819

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!