• Segment set(线段并查集)


    Segment set

    Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 12   Accepted Submission(s) : 4

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    A segment and all segments which are connected with it compose a segment set. The size of a segment set is the number of segments in it. The problem is to find the size of some segment set.

    Input

    In the first line there is an integer t - the number of test case. For each test case in first line there is an integer n (n<=1000) - the number of commands.

    There are two different commands described in different format shown below:

    P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are (x1,y1),(x2,y2).
    Q k - query the size of the segment set which contains the k-th segment.

    k is between 1 and the number of segments in the moment. There is no segment in the plane at first, so the first command is always a P-command.

    Output

    For each Q-command, output the answer. There is a blank line between test cases.

    Sample Input

    1
    10
    P 1.00 1.00 4.00 2.00
    P 1.00 -2.00 8.00 4.00
    Q 1
    P 2.00 3.00 3.00 1.00
    Q 1
    Q 3
    P 1.00 4.00 8.00 2.00
    Q 2
    P 3.00 3.00 6.00 -2.00
    Q 5

    Sample Output

    1
    2
    2
    2
    5
    http://pic002.cnblogs.com/images/2011/287127/2011080416290750.jpg
    做之前学习一下

    线段交叉判断(快速排斥实验 + 跨立实验)

     先进行快速排斥实验;再进行跨立实验
     
     

    如果  p1 × p2 为正数,则相对原点(0,0)来说, p1 p 2 的顺时针方向; 如果p 1  × p2为负数,则p 1 在p 2 的逆时针方向。如果p 1× p =0,则p 1和p 2 模相等且共线,方向相同或相反。

    #include <iostream>
    #include<algorithm>
    using namespace std;
    struct node
    {
        double x,y;
    
    }dian1[1000],dian2[1000];
    int par[1005];
    int num[1005];
    int findi(int x)
    {
        if(par[x]==x)
            return x;
        return par[x]=findi(par[x]);
    }
    void unioni(int x,int y)
    {
        int xx=findi(x);
        int yy=findi(y);
        if(xx!=yy)
        {
            par[xx]=yy;
            num[yy]=num[xx]+num[yy];
    
        }
    }
    double diancheng(node a,node b,node c)
    {
        return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
    }
    int panduan(node a,node b,node c, node d)
    {
        int minpx=min(a.x,b.x);
        int minpy=min(a.y,b.y);
        int minqx=min(c.x,d.x);
        int minqy=min(c.y,d.y);
        int minux=max(minpx,minqx);
        int minuy=max(minpy,minqy);
    
        int maxpx=max(a.x,b.x);
        int maxpy=max(a.y,b.y);
        int maxqx=max(c.x,d.x);
        int maxqy=max(c.y,d.y);
        int maxux=min(maxpx,maxqx);
        int maxuy=min(maxpy,maxqy);
    
        if(minux>maxux||minuy>maxuy)
            return 0;
        if(diancheng(a,b,c)*diancheng(a,b,d)>0)
            return 0;
         if(diancheng(c,d,b)*diancheng(c,d,a)>0)
         return 0;
            return 1;
    
    }
    int main()
    {
       int T;
       cin>>T;
       while(T--)
       {
           int n;
           cin>>n;
           for(int i=0;i<=n;i++)
           {
               par[i]=i;
               num[i]=1;
           }
           char a;
           int k=1;
           while(n--)
           {
               cin>>a;
               if(a=='P')
               {
                   cin>>dian1[k].x>>dian1[k].y>>dian2[k].x>>dian2[k].y;
                   for(int i=1;i<k;i++)
                   {
                       if(panduan(dian1[i],dian2[i],dian1[k],dian2[k]))
                       {
                           unioni(i,k);
                       }
                   }
                   k++;
               }
            else
            {
                int p;
                cin>>p;
                int pp=findi(p);
                cout<<num[pp]<<endl;
            }
           }
           if(T)
            cout<<endl;
       }
        return 0;
    }

    一开始没明白为什么跨立实验就可以解决 为什么要用快速排斥

    应为点乘等于0;有3种可能。

    而通过了快速排斥试验,所以上图左边的情况是不可能出现的,只会出现右边的两种情况。

    左右2种都是 满足相交

  • 相关阅读:
    unity-TextAsset
    unity-热更-InjectFix
    进程和线程的区别
    StringBuffer 和 StringBuilder 的区别
    List、Set、Map 三者区别
    竞态条件是什么?
    多线程安全(synchronized、三大特性、生命周期以及优缺点)
    集合的同步与非同步
    List、Set、Map的了解及区别
    java面试题
  • 原文地址:https://www.cnblogs.com/2014slx/p/7229454.html
Copyright © 2020-2023  润新知