hdu 1558 Segment set

本文介绍了一种结合线段相交判断与并查集数据结构的算法实现,通过具体代码示例展示了如何处理线段集合之间的交并关系,并实现了输入线段集合后能够查询属于同一集合的线段数量的功能。
线段判交+并查集:


#include<iostream>
//#define min(x,y) (x < y ? x : y)
//#define max(x,y) (x > y ? x : y)
using namespace std;
int fa[10000];
int ff(int y)
{
    int t=fa[y];
    while(t!=fa[t])
    {
      t=fa[t];
    }
    return t;
}
struct point{
 double x;
 double y;
};
struct xianduan{
 point a;
 point b;
}c[1000];
double max(double x,double y)
{
  if(x>=y)   return x;
  else      return y;
}
double min(double x,double y)
{
  if(x<=y)   return x;
  else      return y;
}/*
int ff(int x)
{
    int t=fa[x];
    if(t!=fa[t])
    {
     t=fa[t];
    }
    return t;
} 
*/double multiply(point p1,point p2,point p0) 
{ 
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y)); 
}
int intersect(xianduan u,xianduan v) 
{ 
   return( (max(u.a.x,u.b.x)>=min(v.a.x,v.b.x))&&  
  (max(v.a.x,v.b.x)>=min(u.a.x,u.b.x))&& 
  (max(u.a.y,u.b.y)>=min(v.a.y,v.b.y))&&  
  (max(v.a.y,v.b.y)>=min(u.a.y,u.b.y))&& 
  (multiply(v.a,u.b,u.a)*multiply(u.b,v.b,u.a)>=0)&&   
  (multiply(u.a,v.b,v.a)*multiply(v.b,u.b,v.a)>=0));     
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
      int n;
      cin>>n;
      int i=0;
      for(int pp=0;pp<n;pp++)
        fa[pp]=pp;
      for(int k=1;k<=n;k++)
      {
         int sum=0;
         char z;
         cin>>z; 
         switch(z)
         {
          case 'P':
                    cin>>c[i].a.x>>c[i].a.y>>c[i].b.x>>c[i].b.y;
                    for(int j=0;j<i;j++)
                    {
                       if(intersect(c[i],c[j]))
                       {
                         int xx=ff(i);
                         int yy=ff(j);
                         if(xx!=yy)
                         {
                          fa[xx]=yy;
                         }
                       }
                    }
                    i++;
                    break;
          case 'Q':
                  int th;
                  cin>>th;
                  int zz=ff(th-1);
                  for(int j=0;j<i;j++)   
                  {
                    if(ff(j)==zz)
                    sum++;
                  } 
                  cout<<sum<<endl;
                  break;
           }
        }
        if(t!=0)
        cout<<endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值