其实因为判断线段相交的复杂度就是n^2的,所以其实不用并查集,直接暴力做也可以..
因为题目的标号是从1开始的而我的是从0开始的找了好久错...
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct DisjoinSet {
int a[1100];
int s[1100];
void clear(int n) {
for (int i=0;i<=n;i++) {
a[i]=i;
s[i]=1;
}
}
int get(int i) {
if (a[i]==i) return i;
return a[i]=get(a[i]);
}
int getsize(int i) {
return s[get(i)];
}
void tosame(int i,int j) {
i=get(i);j=get(j);
if (i!=j) {
a[i]=j;
s[j]+=s[i];
}
//printf(":: %d %d %d %d %d %d\n",i,j,get(i),get(j),getsize(i),getsize(j));
}
};
struct Point {
double x,y;
Point() {}
Point(Point &a,Point &b) {
x=b.x-a.x;
y=b.y-a.y;
}
void read() {
scanf("%lf%lf",&x,&y);
}
};
struct Line {
Point a,b;
Line() {}
Line(Point &x,Point &y) {
a=x;b=y;
}
void read() {
a.read();b.read();
}
};
int n,m;
Line a[1100];
DisjoinSet c;
double crossmul(const Point &a,const Point &b) {
return a.x*b.y-a.y*b.x;
}
bool isALine(Line &p,Line &q) {
if (crossmul(Point(p.a,p.b),Point(p.b,q.a))==0&&crossmul(Point(p.a,p.b),Point(p.b,q.b))==0) return true;
return false;
}
bool hasCross(Line &p,Line &q) {
if (isALine(p,q)) {
if (max(p.a.x,p.b.x)>=min(q.a.x,q.b.x)||max(p.a.y,p.b.y)>=min(q.a.y,q.b.y)) return true;
return false;
} else {
if (crossmul(Point(p.a,p.b),Point(p.b,q.a))*crossmul(Point(p.a,p.b),Point(p.b,q.b))<=0
&&crossmul(Point(q.a,q.b),Point(q.b,p.a))*crossmul(Point(q.a,q.b),Point(q.b,p.b))<=0) return true;
return false;
}
}
int main() {
int t,i,j,x;
char cc;
scanf("%d",&t);
while (t--) {
scanf("%d",&n);
c.clear(n);
m=0;
for (i=0;i<n;i++) {
scanf(" %c",&cc);
if (cc=='P') {
a[m].read();
for (j=0;j<m;j++) {
if (hasCross(a[j],a[m])) {
//printf("-- %d %d\n",m+1,j+1);
c.tosame(j,m);
}
}
m++;
} else {
scanf("%d",&x);
printf("%d\n",c.getsize(x-1));
}
//for (i=0;i<m;i++) printf("%d ",c.getsize(i));
//printf(" :::\n");
}
if (t) printf("\n");
}
return 0;
}