zoukankan      html  css  js  c++  java
  • Segment set

    题目大意:

      在一个平面上,给定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 }
  • 相关阅读:
    第12组 Alpha冲刺(4/6)
    第12组 Alpha冲刺(3/6)
    第12组 Alpha冲刺(2/6)
    第12组 Alpha冲刺 (1/6)
    第12组(78) 需求分析报告
    第12组(78)团队展示
    结对编程作业
    第06组Beta冲刺(2/5)-(组长)
    第06组Beta冲刺(1/5)-(组长)
    第06组Alpha冲刺(6/6)-(组长)
  • 原文地址:https://www.cnblogs.com/Vincent-Bryan/p/5557910.html
Copyright © 2011-2022 走看看