hdu 1558 并查集+线段相交

                                                             Segment set

                                                    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


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>
#include <stdio.h>
#define eps 1e-7
using namespace std;
const int maxn=1111;
int f[maxn];
int sum[maxn];
struct Node
{
    double x1,x2,y1,y2;
} data[maxn];
void unit(int n)
{
    for(int i=1; i<=n; i++)
    {
        f[i]=i;
        sum[i]=1;
    }
}
int find(int x)
{
    if(x==f[x])
        return x;
    f[x]=find(f[x]);
    return f[x];
}
void un(int a,int b)
{
    int fa=find(a);
    int fb=find(b);
    if(fa==fb) return;
    f[fa]=fb;
    sum[fb]+=sum[fa];
}
double Multiply1(const Node &p,const Node &q)
{
    return (p.x1-p.x2)*(q.y1-p.y1)-(p.y1-p.y2)*(q.x1-p.x1);
}

double Multiply2(const Node &p,const Node &q)
{
    return (p.x1-p.x2)*(q.y2-p.y1)-(p.y1-p.y2)*(q.x2-p.x1);
}
bool Judge(const Node &p,const Node &q)
{
    if(max(p.x1,p.x2)>=min(q.x1,q.x2)&&
            max(q.x1,q.x2)>=min(p.x1,p.x2)&&
            max(p.y1,p.y2)>=min(q.y1,q.y2)&&
            max(q.y1,q.y2)>=min(p.y1,p.y2)&&
            Multiply1(p,q)*Multiply2(p,q)<=eps&&
            Multiply1(q,p)*Multiply2(q,p)<=eps)
        return true;
    else return false;
}
int main()
{
    int t,x;
    char str[2];
    scanf("%d",&t);
    while(t--)
    {
        int k=1;
        int n;
        scanf("%d",&n);
        unit(n);
        while(n--)
        {
            scanf("%s",str);
            if(str[0]=='P')
            {
                scanf("%lf%lf%lf%lf",&data[k].x1,&data[k].y1,&data[k].x2,&data[k].y2);
                for(int i=1; i<k; i++)
                {
                    if(Judge(data[i],data[k]))
                        un(i,k);
                }
                k++;
            }
            else
            {
                scanf("%d",&x);
                x=find(x);
                printf("%d\n",sum[x]);
            }
        }
        if(t)
         printf("\n");
        }
        return 0;
    }


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值