zoukankan      html  css  js  c++  java
  • hdu1558--并查集+判断线段相交

    简单的计算几何题,判断两线段是否相交。将相交的两线段使用并查集归到一类中。查询时输出线段对应集合中元素的个数。

    #include<stdio.h>
    
    struct Point{
    	double x,y;
    };
    struct Segment{
    	Point s,e;
    }node[1010];
    int n,parent[1010];
    int getAbs(int value)
    {
    	if(value>=0)return value;
    	return -value;
    }
    int getParent(int a){
    	while(parent[a]>0)a=parent[a];
    	return a;
    }
    void Union(int a,int b)
    {
    	int r1 = getParent(a);
    	int r2 = getParent(b);
    	if(r1!=r2)
    	{
    		if(r1<r2)
    		{
    			parent[r1]+=parent[r2];//合并两个集合时,计算两个集合的元素个数
    			parent[r2]=r1;
    		}else{
    			parent[r2]+=parent[r1];
    			parent[r1]=r2;
    		}
    	}
    }
    double max(double a,double b)
    {
    	if(a>=b)return a;
    	return b;
    }
    double min(double a,double b)
    {
    	if(a>=b)return b;
    	return a;
    }
    /** 
    * 计算向量 ps,pe的叉积
    */
    double multiply(Point p,Point s,Point e)
    {
    	return (s.x-p.x)*(e.y-p.y)-(e.x-p.x)*(s.y-p.y);
    }
    int main()
    {
    	int t,n,i,j,num,cnt;
    	char command;
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d",&n);
    		cnt=0;
    		//初始时每个元素都是一个集合
    		for(i=1;i<=n;i++)parent[i]=-1;
    		for(i=1;i<=n;i++)
    		{
    			getchar();
    			scanf("%c",&command);
    			if(command=='P'){
    				cnt++;
    				scanf("%lf%lf%lf%lf",&node[cnt].s.x,&node[cnt].s.y,&node[cnt].e.x,&node[cnt].e.y);
    				for(j=1;j<cnt;j++)
    				{
    					//判断第cnt个线段是否与前面的cnt-1个线段有相交。
    					if(max(node[cnt].s.x,node[cnt].e.x)>=min(node[j].s.x,node[j].e.x)
    						&& max(node[j].s.x,node[j].e.x)>=min(node[cnt].s.x,node[cnt].e.x)
    						&& max(node[cnt].s.y,node[cnt].e.y)>=min(node[j].s.y,node[j].e.y)
    						&& max(node[j].s.y,node[j].e.y)>=min(node[cnt].s.y,node[cnt].e.y)
    						&& multiply(node[cnt].s,node[j].s,node[j].e)*multiply(node[cnt].e,node[j].s,node[j].e)<=0
    						&& multiply(node[j].s,node[cnt].s,node[cnt].e)*multiply(node[j].e,node[cnt].s,node[cnt].e)<=0)
    					{
    						//有相交就合并集合
    						Union(cnt,j);
    					}
    				}
    			}else
    			{
    				scanf("%d",&num);
    				//当parent为负数时,其绝对值就是该集合的元素个数。
    				printf("%d
    ",getAbs(parent[getParent(num)]));
    			}
    		}
    		if(t!=0)
    		{
    			printf("
    ");
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    线程池:
    C#:实现托盘
    Linux内核 TCP/IP、Socket参数调优
    redis配置文件redis.conf参数说明
    redis安装与参数说明
    巧用linux服务器的/dev/shm/,如果合理使用,可以避开磁盘IO不给力,提高网站访问速度。
    mkdir:批量创建文件夹
    linux下的shell运算(加、减、乘、除)
    Linux查看文件编码格式及文件编码转换
    解决vi/vim中粘贴会在行首多很多缩进和空格的问题
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3180096.html
Copyright © 2011-2022 走看看