hdu 1558(线段相交+并查集)

来源:互联网 发布:200元算网络诈骗吗 编辑:程序博客网 时间:2024/04/30 17:48

题意:给你一些操作,P后边输入四个值,分别代表一条线段的起点、终点坐标,当输入Q时,后边输入一个整形值K,输出第k条线段所在的集合中包含的线段的个数。


解题思路:线段相交+并查集,sum[i]表示i所在的线段集合中,i为根节点的线段总数。在合并时可以更新。


#include<stdio.h>#include<iostream>using namespace std;struct point{    double x,y;};struct edge{    point a;    point b;}e[1010];int fa[1010],sum[1010];int find(int x){   if(fa[x] == x) return x;   return fa[x] = find(fa[x]);}void Union(int x,int y){    int fx = find(x);    int fy = find(y);    if(fx != fy)    {        fa[fx]=fy;        sum[fy] += sum[fx];    }}double xmult(point a,point b,point c) //大于零代表a,b,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) //a,b,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) //判断ab 与cd是否相交{    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 main(){    int t,n,k,tmp,i,j;    char s[10];    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        k = 0;for(int i = 1; i <= n; i++)sum[i] = 1, fa[i] = i;        for(int i=1;i<=n;i++)        {            scanf("%s",s);            if(s[0]=='P')            {                k++;                scanf("%lf%lf%lf%lf",&e[k].a.x,&e[k].a.y,&e[k].b.x,&e[k].b.y);                for(int j=1;j<k;j++)                    if(Cross(e[k].a,e[k].b,e[j].a,e[j].b))Union(k,j);            }            else if(s[0]=='Q')            {                scanf("%d",&tmp);                printf("%d\n",sum[find(tmp)]);            }        }        if(t) printf("\n");    }    return 0;}


0 0
原创粉丝点击