标签:
题目大意:
在一个平面上,给定N根线段,若某条线段与另一条线段相交,则将它们归于同个集合,给定k,问第k条线段所在的集合中线段的数量。
题目分析:
问题主要考察计算几何和并查集。
首先我们要判断两条线段是否能相交:线段P1P2与线段Q1Q2相交时,向量P1P2是夹在向量P1Q1和向量P1Q2中间,并且向量Q1Q2夹在向量Q1P1和Q1P2中间。这个可以用向量的叉乘来判断,如要判断向量P1P2是夹在向量P1Q1和向量P1Q2中间,只需判断 P1P2×P1Q1 * P1P2×P1Q2 < 0即可。但向量P1P2可能与Q1Q2共线,用刚才的叉乘的方法判别就得是:P1P2×P1Q1 * P1P2×P1Q2 = 0,并且线段P1P2和Q1Q2有部分重叠。
然后就可以用并查集的套路进行解题了。
代码:
1 #include<iostream> 2 using namespace std; 3 static int set[1005]; 4 static int num[1005]; 5 struct point{ 6 double x, y; 7 }; 8 struct edge{ 9 point a, b; 10 }e[1005]; 11 double cross(point a,point b,point c){//三点的叉乘 12 return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); 13 } 14 bool OnSegment(point a,point b,point c){//判断是否有重叠 15 return c.x>=min(a.x,b.x)&&c.x<=max(a.x,b.x)&&c.y>=min(a.y,b.y)&&c.y<=max(a.y,b.y); 16 } 17 18 bool intersect(point a,point b,point c,point d) //判断是否相交 19 { 20 double d1,d2,d3,d4; 21 d1 = cross(c, d, a); 22 d2 = cross(c, d, b); 23 d3 = cross(a, b, c); 24 d4 = cross(a, b, d); 25 if(d1 * d2 < 0 && d3 * d4 < 0) return 1; 26 else if(d1 == 0 && OnSegment(c,d,a)) return 1; 27 else if(d2 == 0 && OnSegment(c,d,b)) return 1; 28 else if(d3 == 0 && OnSegment(a,b,c)) return 1; 29 else if(d4 == 0 && OnSegment(a,b,d)) return 1; 30 return 0; 31 } 32 33 int find(int x){ 34 int temp = x; 35 while( set[temp] != temp ){ 36 temp = set[temp]; 37 } 38 int root = temp; 39 temp = x; 40 while(set[temp] != root){ 41 int t = temp; 42 temp = set[temp]; 43 set[t] = root; 44 } 45 return root; 46 } 47 48 void merge(int x, int y){ 49 int fx = find(x); 50 int fy = find(y); 51 if(fx < fy){ 52 set[fy] = fx; 53 num[fx] += num[fy]; 54 } 55 else if(fx > fy){ 56 set[fx] = fy; 57 num[fy] += num[fx]; 58 } 59 } 60 int main(int argc, char const *argv[]){ 61 int t, n; 62 cin >> t; 63 while(t--){ 64 cin >> n; 65 66 int k = 0; 67 for(int i = 0; i <= n; i++){ 68 set[i] = i; 69 num[i] = 1; 70 } 71 72 while(n--){ 73 string s; 74 cin >> s; 75 if(s == "P"){ 76 k++; 77 cin >> e[k].a.x >> e[k].a.y >> e[k].b.x >> e[k].b.y; 78 for(int j = 1; j <= k; j++){ 79 if(find(k) != find(j) && intersect(e[k].a, e[k].b, e[j].a, e[j].b)) { 80 merge(k,j); 81 //break; 82 } 83 } 84 } 85 else if(s == "Q"){ 86 int m; 87 cin >> m; 88 cout << num[find(m)] << endl; 89 } 90 91 } 92 if(t) cout << endl; 93 } 94 95 return 0; 96 }
标签:
原文地址:http://www.cnblogs.com/Vincent-Bryan/p/5557910.html