hdu1558(并查集和简单几何的结合)

154 篇文章 0 订阅
82 篇文章 0 订阅

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

首先这题就得解决线段相交的判断问题,欢迎观看本博客的简单几何内容大笑

然后重点来了,并查集,还是和基础并查集一样儿一样儿的,不过,这里有个记录问题,记录每个父亲的儿子数量,我用num数组来记录,在合并的时候将后来的父亲加上先前两个父亲的num值就ok了,不过写博客的时候突然想到了一种脑洞办法——遍历(hhhhhhhhh)试了一下也还是过了,艾玛自己想数组的办法想了好久好久结果一来写博客想到了脑洞办法竟然也可以过委屈哭,亏我想数组办法调试了好久好久啊啊啊啊!!!



#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<memory.h>
using namespace std;

typedef struct node
{
    double x,y;
}Point;
typedef struct line
{
   Point start,end;
}vector;
double mul(Point p1,Point p2,Point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
bool cross(vector v1,vector v2)
{
    if(max(v1.start.x,v1.end.x)>=min(v2.start.x,v2.end.x)&&
       max(v2.start.x,v2.end.x)>=min(v1.start.x,v1.end.x)&&
       max(v1.start.y,v2.end.y)>=min(v2.start.y,v2.end.y)&&
       max(v2.start.y,v2.end.y)>=min(v1.start.y,v1.end.y)&&
       mul(v2.start,v1.end,v1.start)*mul(v1.end,v2.end,v1.start)>=0&&
       mul(v1.start,v2.end,v2.start)*mul(v2.end,v1.end,v2.start)>=0
       )
        return true;
    return false;
}


vector f[100010];int fa[100010];int num[100010];


int ff(int x)
{
    int tem=fa[x];
    if(tem!=x)
    fa[x]=ff(tem);
    return fa[x];
}

void join(int a,int b)
{
    int tem=num[fa[ff(a)]]+num[fa[ff(b)]];
    fa[ff(a)]=fa[ff(b)];
   // cout<<a<<' '<<b<<endl;
   // cout<<fa[ff(a)]<<endl;
   // cout<<" num[fa[ff(a)]] = "<<num[fa[ff(a)]]<<" num[fa[ff(b)]] = "<<num[fa[ff(a)]]<<endl;
    num[fa[ff(a)]]=tem;
    //cout<<a<<" and "<<b<<"de father shi "<<ff(a)<<endl;
   // cout<<"zhe ge ji he bao han "<<num[fa[ff(a)]]<<" ge xian duan"<<endl;

}

int main()
{
    int t;
    scanf("%d",&t);
    for(int u=0;u<t;u++)
    {
        for(int i=0;i<100010;i++)
        fa[i]=i;
        memset(num,0,sizeof(num));
        int n;
        scanf("%d",&n);
        int g=0;
        for(int i=1;i<=n;i++)
        {
            char cc;scanf(" %c",&cc);
            if(cc=='P')
            {
                g++;
                scanf("%lf%lf%lf%lf",&f[g].start.x,&f[g].start.y,&f[g].end.x,&f[g].end.y);
                num[g]++;
                for(int j=1;j<g;j++)
                    if(cross(f[g],f[j])>0&&ff(fa[g])!=ff(fa[j]))
                        join(fa[g],fa[j]);
            }
            else
            {
                int p;
                scanf("%d",&p);
                printf("%d\n",num[ff(fa[p])]);
            }

        }
        if(u!=t-1)
        printf("\n");
    }
    return 0;
}



下面是脑洞代码:

#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<memory.h>
using namespace std;

typedef struct node
{
    double x,y;
}Point;
typedef struct line
{
   Point start,end;
}vector;
double mul(Point p1,Point p2,Point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
bool cross(vector v1,vector v2)
{
    if(max(v1.start.x,v1.end.x)>=min(v2.start.x,v2.end.x)&&
       max(v2.start.x,v2.end.x)>=min(v1.start.x,v1.end.x)&&
       max(v1.start.y,v2.end.y)>=min(v2.start.y,v2.end.y)&&
       max(v2.start.y,v2.end.y)>=min(v1.start.y,v1.end.y)&&
       mul(v2.start,v1.end,v1.start)*mul(v1.end,v2.end,v1.start)>=0&&
       mul(v1.start,v2.end,v2.start)*mul(v2.end,v1.end,v2.start)>=0
       )
        return true;
    return false;
}


vector f[100010];int fa[100010];

int ff(int x)
{
    int tem=fa[x];
    if(tem!=x)
    fa[x]=ff(tem);
    return fa[x];
}

void join(int a,int b)
{
    fa[ff(a)]=fa[ff(b)];
}

int main()
{
    int t;
    scanf("%d",&t);
    for(int u=0;u<t;u++)
    {
        for(int i=0;i<100010;i++)
        fa[i]=i;
        int n;
        scanf("%d",&n);
        int g=0;
        for(int i=1;i<=n;i++)
        {
            char cc;scanf(" %c",&cc);
            if(cc=='P')
            {
                g++;
                scanf("%lf%lf%lf%lf",&f[g].start.x,&f[g].start.y,&f[g].end.x,&f[g].end.y);
                for(int j=1;j<g;j++)
                    if(cross(f[g],f[j])>0&&ff(fa[g])!=ff(fa[j]))
                        join(fa[g],fa[j]);
            }
            else
            {
                int p;
                scanf("%d",&p);
                int t=ff(p),s=0;
                for(int i=0;i<=g;i++)
                if(ff(i)==t)
                s++;
                printf("%d\n",s);
            }

        }
        if(u!=t-1)
        printf("\n");
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值