判断第k个线段的集合中一共有几条线段。
先用并查集将相交的线段合并记录,最后查询sum数组即可。
#include<iostream> #include<string> #include<cstring> using namespace std; struct node { double x; double y; }s[2004]; struct edge { node a,b; int num; }E[2005]; int fa[2005]; int sum[2005]; int T,n,cha; char c; int m=0; double direction (node p0, node p1, node p2) { return ((p2.x - p0.x)*(p1.y - p0.y) - (p1.x - p0.x)*(p2.y - p0.y)); } bool on_segment (node p0, node p1, node p2)//判断线段相交 { double minx, maxx, miny, maxy; minx = min(p0.x, p1.x); maxx = max(p0.x, p1.x); miny = min(p0.y, p1.y); maxy = max(p0.y, p1.y); if (p2.x >= minx && p2.x <= maxx && p2.y >= miny && p2.y <= maxy) return true; else return false; } bool segments_intersect (node p1, node p2, node p3, node p4) { double d1, d2, d3, d4; d1 = direction(p3, p4, p1); d2 = direction(p3, p4, p2); d3 = direction(p1, p2, p3); d4 = direction(p1, p2, p4); if (((d1 < 0 && d2 > 0) || (d1 > 0 && d2 < 0)) && ((d3 < 0 && d4 > 0) || (d3 > 0 && d4 < 0))) return true; else if (d1 == 0 && on_segment(p3, p4, p1)) return true; else if (d2 == 0 && on_segment(p3, p4, p2)) return true; else if (d3 == 0 && on_segment(p1, p2, p3)) return true; else if (d4 == 0 && on_segment(p1, p2, p4)) return true; else return false; } //并查集操作 void init() { for(int i=1;i<=n;i++) { fa[i]=i; sum[i]=1; } } int find(int x) { if(x!=fa[x]) fa[x]=find(fa[x]); return fa[x]; } void combine(int x,int y) { int xx=find(x); int yy=find(y); if(xx==yy) return ; fa[xx]=yy; sum[yy]+=sum[xx]; } int main() { cin>>T; while(T--) { cout<<(m++?"\n":""); cin>>n; init(); int cixu=1; for(int i=1;i<=n;i++) { cin>>c; if(c=='P') { cin>>E[cixu].a.x>>E[cixu].a.y>>E[cixu].b.x>>E[cixu].b.y; E[cixu].num=cixu; for(int j=1;j<cixu;j++) { if(segments_intersect(E[j].a,E[j].b,E[cixu].a,E[cixu].b)) { combine(E[j].num,E[cixu].num); } } cixu++; } if(c=='Q') { cin>>cha; cout<<sum[find(cha)]<<endl; } } } return 0; }