hdu 1558

# include <iostream>
# include <stdio.h>
using namespace std;
int num[1010],pre[1010];
char s[5];
struct point
{
	double x,y;
};
struct Edge
{
	point a,b;
}E[1010];


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 Find(int x)
{
	return x==pre[x]?x:pre[x]=Find(pre[x]);
}
void unin(int i,int j)
{
	int x=Find(i);
	int y=Find(j);
	if(x!=y)
	{
		pre[y]=x;
		num[x]+=num[y];
	}
}
int main ()
{
	int T,n;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		int i;
		for(i=1;i<=n;i++)
		{
			pre[i]=i;
			num[i]=1;
		}
		int j=0;
		for(i=1;i<=n;i++)
		{
			int k;
			scanf("%s",s);
			if(s[0]=='P')
			{
			    j++;
				scanf("%lf%lf%lf%lf",&E[j].a.x,&E[j].a.y,&E[j].b.x,&E[j].b.y);
				for(k=1;k<j;k++)
				{
				    //printf("%d  %d  \n",Cross(E[j].a,E[j].b,E[k].a,E[k].b),Find(k)!=Find(j));
					if(Find(k)!=Find(j)&&Cross(E[j].a,E[j].b,E[k].a,E[k].b))
						{unin(k,j);}
				}
			}
			else if(s[0]=='Q')
			{
				int temp;
				scanf("%d",&temp);
				printf("%d\n",num[Find(temp)]);
			}
		}
		if(T)   printf("\n");
	}
	return 0;
}


//详细解法看算法导论
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值