HDU 1558 Segment set 并查集 线段相交

Segment set
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Submit

Status
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<stdio.h>
#include<string>
#include<cstring>
#include<queue>
#include<algorithm>
#include<functional>
#include<vector>
#include<iomanip>
#include<math.h>
#include<iostream>
#include<sstream>
#include<stack>
#include<set>
#include<map>
using namespace std;
const int MAX=1005;
struct point
{
    double x,y;
};
struct edge
{
    point a,b;
};
edge edges[MAX];
double xmult(point a,point b,point c)
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
bool OnSegment(point a,point b,point c)
{
    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);
}
bool Cross(point a,point b,point c,point d)
{
    double d1,d2,d3,d4;
    d1=xmult(c,d,a);
    d2=xmult(c,d,b);
    d3=xmult(a,b,c);
    d4=xmult(a,b,d);
    if(d1*d2<0&&d3*d4<0)  return 1;
    else    if(d1==0&&OnSegment(c,d,a)) return 1;
    else    if(d2==0&&OnSegment(c,d,b)) return 1;
    else    if(d3==0&&OnSegment(a,b,c)) return 1;
    else    if(d4==0&&OnSegment(a,b,d)) return 1;
    return 0;
}
int pre[MAX],sz[MAX];
int Find(int x)
{
    int r=x;
    while(r!=pre[r])
        r=pre[r];
    int i=x,j;
    while(pre[i]!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;
}
void mix(int x,int y)
{
    int fx=Find(x),fy=Find(y);
    if(fx!=fy)
    {
        pre[fy]=fx;
        sz[fx]=sz[fx]+sz[fy];
    }
}
int main()
{
    cin.sync_with_stdio(false);
    int T,N,cnt,temp;
    char command;
    cin>>T;
    while (T--)
    {
        for (int i=0; i<MAX; i++) pre[i]=i,sz[i]=1;
        cin>>N;
        cnt=1;
        for (int i=0; i<N; i++)
        {
            cin>>command;
            if (command=='P')
            {
                cin>>edges[cnt].a.x>>edges[cnt].a.y>>edges[cnt].b.x>>edges[cnt].b.y;
                for (int i=1; i<cnt; i++)
                {
                    if (Cross(edges[i].a,edges[i].b,edges[cnt].a,edges[cnt].b))
                        mix(i,cnt);
                }
                cnt++;
            }
            else
            {
                cin>>temp;
                cout<<sz[Find(temp)]<<endl;
            }
        }
        if (T)
            cout<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值