屌絲真心覺得這題的計算幾何味道遠大於並查集,花了兩天時間纔想明白怎麼判斷兩條直線相交,結果還寫不對,。。。。。
code:
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-8;
int decmp(double n)
{
if(fabs(n)<eps)
{
return 0;
}
return n>0 ? 1:-1;
}
struct Point
{
double x,y;
};
struct Seg
{
Point s,e;
}segs[1001];
double direction(Point l,Point r,Point m)
{
//vector a (l.x-m.x,l.y-m.y)
//vector b (r.x-m.x,r.y-m.y)
return (l.x-m.x)*(r.y-m.y) - (r.x-m.x)*(l.y-m.y);
}
bool isIntersert(Seg a,Seg b)
{
int d1,d2,d3,d4;
d1=decmp(direction(a.s,a.e,b.s));
d2=decmp(direction(a.s,a.e,b.e));
d3=decmp(direction(b.s,b.e,a.s));
d4=decmp(direction(b.s,b.e,a.e));
//規範相交
if( d1*d2 <0 && d3*d4 <0)
{
return true;
}
//端點相交
if( d1*d2 ==0 || d3*d4==0 )
{
return true;
}
return false;
}
int num[1001],rank[1001],fa[1001];
void init()
{
for(int i=1;i<=1000;i++)
{
num[i]=1;
rank[i]=0;
fa[i]=i;
}
}
int find(int k)
{
if(k!=fa[k])
{
fa[k]=find(fa[k]);
}
return fa[k];
}
void merge(int x,int y)
{
if(!isIntersert(segs[x],segs[y]))
{
return ;
}
x=find(x);
y=find(y);
if(x!=y)
{
if(rank[x]<rank[y])
{
fa[x]=y;
num[y]+=num[x];
}else{
fa[y]=x;
num[x]+=num[y];
if(rank[x]==rank[y])
{
rank[x]++;
}
}
}
}
int main()
{
int cas,n,cnt,i,j,k;
char str[2];
scanf("%d",&cas);
while(cas--)
{
scanf("%d",&n);
cnt=0;
init();
for(i=1;i<=n;i++)
{
scanf("%s",str);
if(str[0]=='P')
{
++cnt;
scanf("%lf%lf",&segs[cnt].s.x,&segs[cnt].s.y);
scanf("%lf%lf",&segs[cnt].e.x,&segs[cnt].e.y);
for(j=1;j<cnt;j++)
{
merge(j,cnt);
}
}else{
scanf("%d",&k);
k=find(k);
printf("%d\n",num[k]);
}
}
if(cas)
{
puts("");
}
}
return 0;
}