ACM 学习之 并查集

                 hdu 1558 http://acm.hdu.edu.cn/showproblem.php?pid=1558

                 很久没有a题  一些小细节都忘了输出错了了几次,并查集的最基本方式都差点忘了,今天小复习一下。比较简单的并查集,先判断两个线段相交,再用并查集看是否合

并,只要注意集合大小的合并即可解决,下面是code:

 

   

 

#include <cstdio>

const int maxn=10000;
int father[maxn];
int num[maxn];

struct Segment{
	double x1,y1;		//表示线段
	double x2,y2;
}s[maxn];

double  x,y;

void Init(){
	for(int i=0;i<maxn;i++){
		father[i]=i;
		num[i]=1;
	}
}

int Find(int x){
	if(father[x]==x)	return x;
	return father[x]=Find(father[x]);
}

void UnionSet(int i,int j){
	father[j]=i;
	num[i]+=num[j];
}



void Solve(Segment s1,Segment s2)
{    
    if(s1.x2==s1.x1&&s2.x2!=s2.x1)
    {
        x=s1.x2;
        y=((s2.y2-s2.y1)/(s2.x2-s2.x1))*(x-s2.x2)+s2.y2;
    }
    else{
        if(s2.x2==s2.x1&&s1.x2!=s1.x1)
        {    
            x=s2.x2;
            y=((s1.y2-s1.y1)/(s1.x2-s1.x2))*(x-s1.x2)+s1.y2;
        }
        else
        {
            double k1=(s1.y2-s1.y1)/(s1.x2-s1.x1);
            double k2=(s2.y2-s2.y1)/(s2.x2-s2.x1);
            double b1=s1.y2-k1*s1.x2;
            double b2=s2.y2-k2*s2.x2;
            x=(b2-b1)/(k1-k2);
            y=k1*x+b1;
        }
    }
}

bool Dic(Segment s1){
	double tx1=s1.x1<s1.x2?s1.x1:s1.x2;
	double ty1=s1.y1<s1.y2?s1.y1:s1.y2;
	double tx2=s1.x1>s1.x2?s1.x1:s1.x2;
	double ty2=s1.y1>s1.y2?s1.y1:s1.y2;
	if(tx1<=x&&x<=tx2&&ty1<=y&&y<=ty2)
		return true;
	return false;
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		Init();
		int k=0;
		while(n--){
			char op[5];
			scanf("%s",op);	
			if(op[0]=='P'){	
				x=maxn;
				y=maxn;
				scanf("%lf%lf%lf%lf",&s[k].x1,&s[k].y1,&s[k].x2,&s[k].y2);
				for(int i=0;i<=k-1;i++){
					Solve( s[i], s[k]);
					if(Dic(s[i])&&Dic(s[k])){
						int ti=Find(i);
						int tj=Find(k);
						if(ti!=tj){
							UnionSet(ti,tj);		
						//	break;
						}
					}
				}
				k++;
			}
			else{
				int k1;
				scanf("%d",&k1);
				k1=Find((k1-1));
				printf("%d\n",num[k1]);
			}
		}
		if(t>0) puts("");
	}
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值