大意:
支持两种操作:
P x1,y1,x2,y2 插入一条线段
Q x 输出第x条线段直接或间接与它相交的线段的数量+1(它自身)。
思路:
以此判断与之前的线段相交,如果相交就合并集合,并查集模板与判断线段相交模板水过。
TIP:
样例之间需要输出空行。
#include <iostream>
#include <vector>
#include <string.h>
#include <stdio.h>
using namespace std;
struct Point
{
double x,y;
};
struct line
{
Point a,b;
}l[1005];
double mult(Point a, Point b, Point c)
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
bool intersect(Point aa, Point bb, Point cc, Point dd)
{
if ( max(aa.x, bb.x)<min(cc.x, dd.x) )
{
return 0;
}
if ( max(aa.y, bb.y)<min(cc.y, dd.y) )
{
return false;
}
if ( max(cc.x, dd.x)<min(aa.x, bb.x) )
{
return 0;
}
if ( max(cc.y, dd.y)<min(aa.y, bb.y) )
{
return 0;
}
if ( mult(cc, bb, aa)*mult(bb, dd, aa)<0 )
{
return 0;
}
if ( mult(aa, dd, cc)*mult(dd, bb, cc)<0 )
{
return 0;
}
return 1;
}
struct UFS
{
int father[1100],rank[1100],num[1100];
UFS(int n)
{
for(int i=0; i<n; i++)
{
father[i]=i;
rank[i]=0;
num[i]=1;
}
}
int find(int v)
{
return father[v]=father[v]==v?v:find(father[v]);
}
void merge(int x,int y)
{
int a=find(x),b=find(y);
if(a==b) return;
if(rank[a]<rank[b])
{
father[a]=b;
num[b]+=num[a];
}
else
{
father[b]=a;
num[a]+=num[b];
if(rank[a]==rank[b])
++rank[a];
}
}
};
int main()
{
int T,n,x;
char ord[10];
scanf("%d",&T);
while(T--)
{
int cnt=0;
scanf("%d",&n);
UFS u1(n);
while(n--)
{
scanf("%s",ord);
if(ord[0]=='P')
{
scanf("%lf%lf%lf%lf",&l[cnt].a.x,&l[cnt].a.y,&l[cnt].b.x,&l[cnt].b.y);
for(int i=0;i<cnt;i++)
{
if(intersect(l[i].a,l[i].b,l[cnt].a,l[cnt].b))
u1.merge(i,cnt);
}
cnt++;
}
if(ord[0]=='Q')
{
scanf("%d",&x);
int ans=u1.find(x-1);
printf("%d\n",u1.num[ans]);
}
}
if(T!=0)
printf("\n");
}
return 0;
}