hdu 1558 Segment set 5.1.4

10 篇文章 0 订阅
1 篇文章 0 订阅

这题哪里是考并查集啊……分明在考几何………………几何无能者抄之……

Segment set

Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 45 Accepted Submission(s): 19
 
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
 

#include <iostream>
using namespace std;
#define SIZE 1001
#define MAX(a,b) (a>b?a:b)  
#define MIN(a,b) (a<b?a:b) 

struct point{
       double x,y;
       }line[SIZE][2];
int p[SIZE];


inline bool across(int i,int j)
{
       double x1,x2,x3,y1,y2,y3;
       x1=line[i][0].x-line[j][0].x;
       y1=line[i][0].y-line[j][0].y;
       x2=line[j][1].x-line[j][0].x;
       y2=line[j][1].y-line[j][0].y;
       x3=line[i][1].x-line[j][0].x;
       y3=line[i][1].y-line[j][0].y;
       return (x1*y2-x2*y1)*(x2*y3-x3*y2)>=0;
}

inline bool isRecIntersect(int i,int j)
{
       return MAX(line[i][0].x,line[i][1].x)>=MIN(line[j][0].x,line[j][1].x) &&  
           MAX(line[i][0].y,line[i][1].y)>=MIN(line[j][0].y,line[j][1].y);
       }

inline bool isIntersect(int i,int j)
{return isRecIntersect(i,j)&&isRecIntersect(j,i)&&across(i,j)&&across(j,i);}
    
int find(int x)
{
    if(p[x]<0)//p[x]less than 0 mean's it is root and connected to -p[x] segment.
    //else mean it is not root and root is p[x].
    return x;
    else
    return p[x]=find(p[x]);
} 
    
       
void merge(int x,int y)
{
     int fx=find(x),fy=find(y);
     int ff=p[fx]+p[fy];
     if(fx!=fy&&isIntersect(x,y))
     {
         if(p[fx]>p[fy])
         {
             p[fx]=fy;
             p[fy]=ff;
         }
         else
         {
             p[fy]=fx;
             p[fx]=ff;
         }
     }
}

int main()
{
    int cas;
    cin>>cas;
    while(cas--)
    {
        memset(p,-1,sizeof(p));
        int c;
        int i;
        int n=1;
        cin>>c;
        while(c--)
        {
            char cmd[2];
            cin>>cmd;
            if(cmd[0]=='P')
            {
                cin>>line[n][0].x>>line[n][0].y>>line[n][1].x>>line[n][1].y;
                for(i=1;i<n;i++)
                    merge(i,n);
                n++;
            }
            else
            {
                cin>>i;
                cout<<-p[find(i)]<<endl;
            }
        }
        if(cas)//if not the last cas
            puts("");
    }
//    system("pause");
    return 0;
}
   

粘贴党:

可以用向量来判断线段是否相交:

    ①快速排斥试验: 设以线段P0P1为对角线的矩形为R, 以Q0Q1为对角线的矩形为T, 若R与T不相交, 则显然这两条线段不相交. 这个过程可以用包围盒判别来做, 细节请看isRecIntersect();

    ②跨立试验: 若两线段相交, 则它们必然互相跨立对方. 若P0P1跨立Q0Q1, 则Q0P0与Q0P1分别位于Q0Q1两侧, 由向量叉积的性质, ( Q0Px Q0Q1) * (Q0Q1 x Q0P1) > 0. 同理, 若Q0Q1跨立P0P1, 则P0Q0与P0Q1分别位于P0P1两侧, 所以 ( P0Q0 x  P0P1) * ( P0Qx  P0P1) > 0. 考虑到线段的端点可能在另一条线段上的情况, 上面的 > 可以改为 >= . 实现细节请看across().


话说这题快速排斥试验有没有好像是一样的……

假装我看懂了这个见鬼的跨立……让我想到军训了……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值