【计算几何初步-线段相交+并查集】【HDU1558】Segment set

Segment set

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3548    Accepted Submission(s): 1324


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

【计算几何初步-线段相交+并查集】【HDU1558】Segment set_第1张图片
 

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 in the plane at first, so the first command is always a P-command.
 

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

Sample Input
   
   
   
   
1 10 P 1.00 1.00 4.00 2.00 P 1.00 -2.00 8.00 4.00 Q 1 P 2.00 3.00 3.00 1.00 Q 1 Q 3 P 1.00 4.00 8.00 2.00 Q 2 P 3.00 3.00 6.00 -2.00 Q 5
 

Sample Output
   
   
   
   
1 2 2 2 5
 

Author
LL
 



主要可能会直线重叠的情况,此时也算相交

所以若叉积为0 点积也为0时也算相交

代码如下:

#include <cstdio>  
#include <cstdlib>  
#include <cmath>  
#include <cstring>  
#include <ctime>  
#include <algorithm>  
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313   
#define exp 0.000001
using namespace std;
int N,tot;
struct point
{
	double x,y;
};
point S[10110],E[10011];
int Set[10110];
int ANS[10110];
int sgn(double x)
{
	if(fabs(x)<exp) return 0;
	else if(x<0) return -1;
	else return 1;
}
double dotdet(double x1,double y1,double x2,double y2)
{
	return x1*x2+y1*y2;
}
double dot(point a,point b,point c)
{
	return dotdet(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
double crossdet(double x1,double y1,double x2,double y2)
{
	return x1*y2-x2*y1;
}
double cross(point a,point b,point c)
{
	return crossdet(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
double pan(point s1,point e1,point s2,point e2)
{
	//跨立实验 
	double a1=cross(s1,e1,s2);  //s1-e1 s2
	double a2=cross(s1,e1,e2);
	double a3=cross(s2,e2,s1);
	double a4=cross(s2,e2,e1);
	if(sgn(a1*a2)<0&&sgn(a3*a4)<0) return 1;
	if((a1==0&&sgn(dot(s2,s1,e1))<=0)||
	   (a2==0&&sgn(dot(e2,s1,e1))<=0)||
	   (a3==0&&sgn(dot(s1,s2,e2))<=0)||
	   (a4==0&&sgn(dot(e1,s2,e2))<=0))
	   return 1;
	return 0;
}
void CSH()
{
	for(int i=0;i<=10001;i++)
	{
	Set[i]=i;
	ANS[i]=1;
	}
	tot=0;
}
int find(int x)
{
	if(x!=Set[x]) 
	Set[x]=find(Set[x]);
	return Set[x];
}
void UNION(int a,int b)
{
	int a1=find(a);
	int a2=find(b);
	if(a1!=a2)
	{	
		ANS[a1]+=ANS[a2];
		Set[a2]=a1;
	}
}
void input()
{
	char ch;int temp;
	CSH();
	cin>>N;
	getchar();
	for(int i=1;i<=N;i++)
	{
        scanf("%c",&ch);
		if(ch=='P')
		{
			tot++; 
			scanf("%lf%lf%lf%lf\n",&S[tot].x,&S[tot].y,&E[tot].x,&E[tot].y);
			for(int i=1;i<tot;i++)
			{
				if(pan(S[i],E[i],S[tot],E[tot])==1)
				{
					UNION(i,tot);
				}	
			}
		}
		else if(ch=='Q')
		{
			scanf("%d\n",&temp);
			cout<<ANS[find(temp)]<<endl;
		}
	}
}
void init()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout); 
}
int main()
{
	int T;
//	init();
	cin>>T;
	int nn=0;
	while(T--)
	{
		if(nn++) cout<<endl;
		input();		
	}
	return 0;
}
  


你可能感兴趣的:(【计算几何初步-线段相交+并查集】【HDU1558】Segment set)