思路:
每加入一条线段,判断它与之前的线段是否相交,若相交,则合并两个集合
#include<iostream> #include<fstream> #include<cstdlib> #include<iomanip> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define REP(i,l,r) for(int i=(l);i<=(r);++i) #define REP2(i,l,r) for(int i=(l);i>=(r);--i) #define CLR(a,v) memset(a,v,sizeof(a)) #define sqr(x) ((x)*(x)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define SCAN(n) scanf("%d",&n) #define SCAN2(n,m) scanf("%d %d",&n,&m) #define SCANS(s) scanf("%s",s); #define PRINT(n) printf("%d\n",n) using namespace std; typedef long long ll; const int INF=1e9; const double eps=1e-9; const int MOD=(int)1e9+7; const int N=100010; /*------------------------------------------------------------------------*/ struct setment{ double x1,y1,x2,y2; }s[1010]; int arr[1010],num[1010]; int find(int x){ int t=x; while(arr[t]!=t){ t=arr[t]; } arr[x]=t; return t; } bool is_cross(const setment& s1,const setment& s2){ if(min(s1.x1,s1.x2)>max(s2.x1,s2.x2)||min(s1.y1,s1.y2)>max(s2.y1,s2.y2)|| max(s1.x1,s1.x2)<min(s2.x1,s2.x2)||max(s1.y1,s1.y2)<min(s2.y1,s2.y2)) return 0; double i,j,k,l; i=(s1.x2-s1.x1)*(s2.y1-s1.y1)-(s1.y2-s1.y1)*(s2.x1-s1.x1); j=(s1.x2-s1.x1)*(s2.y2-s1.y1)-(s1.y2-s1.y1)*(s2.x2-s1.x1); k=(s2.x2-s2.x1)*(s1.y1-s2.y1)-(s2.y2-s2.y1)*(s1.x1-s2.x1); l=(s2.x2-s2.x1)*(s1.y2-s2.y1)-(s2.y2-s2.y1)*(s1.x2-s2.x1); return i*j<=eps&&k*l<=eps; } int main(){ int t,n,m; char str[5]; SCAN(t); while(t--){ SCAN(n); int cnt=1; REP(i,1,1001){ arr[i]=i; num[i]=1; } while(n--){ SCANS(str); if(str[0]=='P'){ scanf("%lf%lf%lf%lf",&s[cnt].x1,&s[cnt].y1,&s[cnt].x2,&s[cnt].y2); REP(i,1,cnt-1) if(is_cross(s[i],s[cnt])){ int x=find(i),y=find(cnt); if(x!=y){ arr[x]=y; num[y]+=num[x]; } } ++cnt; } else{ SCAN(m); m=find(m); PRINT(num[m]); } } if(t) printf("\n"); } return 0; }