hdu1558 Segment set

#include<stdio.h>
#include <stdlib.h>
#define MAXN 1005

int father[MAXN],num[MAXN];

typedef struct node
{
	double x,y;
}point;

struct edge
{
	point p1;
	point p2;
} seg[MAXN];

double Max(double x,double y)
{
	return x>y?x:y;
}

double Min(double x,double y)
{
	return x<y?x:y;
}

int find(int x)
{
	//带路径压缩的查找算法
	int i,r;
	r=x;
	while(r!=father[r])//循环结束,则找到根节点
		r=father[r];
	i=x;
	while(i!=r)//本循环修改查找路径中所有节点
	{
		int j=father[i];
		father[i]=r;
		i=j;
	}
	return r;
}

void Union(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if (fx!=fy)
	{
		father[fx]=fy;
		num[fy]+=num[fx];
	}
}

double mult(point a,point b,point c)
{
	return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}

int onSegment(point a,point b,point c)
{
	if(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))
		return 1;
	else
		return 0;
}

int segCross(point a,point b,point c,point d)
{
	double d1,d2,d3,d4;
	d1=mult(c,d,a);
	d2=mult(c,d,b);
	d3=mult(a,b,c);
	d4=mult(a,b,d);
	// printf("*****%lf %lf %lf %lf\n",d1,d2,d3,d4);
	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,n,i,j,s,k;
	char ch;
	scanf("%d",&t);
	while(t--)
	{
		k=0;
		scanf("%d",&n);
		for (i=1; i<=n; i++)
		{
			father[i]=i;
			num[i]=1;
		}
		for (i=1; i<=n; i++)
		{
			getchar();
			scanf("%c",&ch);
			if(ch=='P')
			{
				k++;
				scanf("%lf %lf %lf %lf",&seg[k].p1.x,&seg[k].p1.y,&seg[k].p2.x,&seg[k].p2.y);
				for (j=1; j<k; j++)
				{
					if((find(k)!=find(j))&&(segCross(seg[k].p1,seg[k].p2,seg[j].p1,seg[j].p2)))
						Union(k,j);
				}
			}
			else if(ch=='Q')
			{
				scanf("%d",&s);
				printf("%d\n",num[find(s)]);
			}
		}
		if(t)
			printf("\n");
	}
	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值