hdu 1558 线段相交+并查集

题意:要求相交的线段都要塞进同一个集合里

sol:并查集+判断线段相交即可。n很小所以n^2就可以水过

  1 #include <iostream>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <cstdio>
  5 using namespace std;
  6
  7 int f[1010];
  8 char ch;
  9 int tmp,n;
 10 double X1,X2,Y1,Y2;
 11
 12    #define eps 1e-8
 13    #define PI acos(-1.0)//3.14159265358979323846
 14    //判断一个数是否为0,是则返回true,否则返回false
 15    #define zero(x)(((x)>0?(x):-(x))<eps)
 16    //返回一个数的符号,正数返回1,负数返回2,否则返回0
 17    #define _sign(x)((x)>eps?1:((x)<-eps?2:0))
 18   struct point
 19   {
 20       double x,y;
 21       point(){}
 22       point(double xx,double yy):x(xx),y(yy)
 23       {}
 24   };
 25   struct line
 26   {
 27       point a,b;
 28       line(){}      //默认构造函数
 29       line(point ax,point bx):a(ax),b(bx)
 30       {}
 31   }l[1010];//直线通过的两个点,而不是一般式的三个系数
 32
 33    //求矢量[p0,p1],[p0,p2]的叉积
 34    //p0是顶点
 35    //若结果等于0,则这三点共线
 36    //若结果大于0,则p0p2在p0p1的逆时针方向
 37    //若结果小于0,则p0p2在p0p1的顺时针方向
 38    double xmult(point p1,point p2,point p0)
 39    {
 40        return(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
 41    }
 42    //计算dotproduct(P1-P0).(P2-P0)
 43    double dmult(point p1,point p2,point p0)
 44    {
 45        return(p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
 46    }
 47    //两点距离
 48    double distance(point p1,point p2)
 49    {
 50        return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
 51    }
 52    //判三点共线
 53    int dots_inline(point p1,point p2,point p3)
 54    {
 55        return zero(xmult(p1,p2,p3));
 56    }
 57    //判点是否在线段上,包括端点
 58    int dot_online_in(point p,line l)
 59    {
 60        return zero(xmult(p,l.a,l.b))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&(l.a.y-p.y)*(l.b.y-p.y)<eps;
 61    }
 62    //判点是否在线段上,不包括端点
 63    int dot_online_ex(point p,line l)
 64    {
 65        return dot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y));
 66    }
 67    //判两点在线段同侧,点在线段上返回0
 68    int same_side(point p1,point p2,line l)
 69    {
 70        return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps;
 71    }
 72    //判两点在线段异侧,点在线段上返回0
 73    int opposite_side(point p1,point p2,line l)
 74    {
 75        return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps;
 76    }
 77    //判两直线平行
 78    int parallel(line u,line v)
 79    {
 80        return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y));
 81    }
 82    //判两直线垂直
 83    int perpendicular(line u,line v)
 84    {
 85        return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y));
 86    }
 87    //判两线段相交,包括端点和部分重合
 88    int intersect_in(line u,line v)
 89    {
 90        if(!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))
 91            return!same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);
 92        return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);
 93    }
 94 int find(int x)
 95 {
 96     if (f[x]!=x)
 97         f[x]=find(f[x]);
 98     return f[x];
 99 }
100
101 void iunion(int x,int y)
102 {
103     int fx,fy;
104     fx=find(x);
105     fy=find(y);
106     if (fx!=fy)
107         f[fx]=fy;
108 }
109
110 int main()
111 {
112     //freopen("in.txt","r",stdin);
113     int times;
114     cin>>times;
115     while(times--)
116     {
117
118     cin>>n;
119     int T=0;
120     for (int i=1;i<=n;i++)
121     {
122         /*
123         cout<<"dev: ";
124         for (int j=1;j<=T;j++)
125             cout<<f[j]<<" ";
126         cout<<endl;
127         */
128         cin>>ch;
129         if (ch==‘Q‘)
130         {
131             cin>>tmp;
132             int ans=0;
133             for (int j=1;j<=T;j++)
134                 if (find(tmp)==find(j))     ans++;
135             cout<<ans<<endl;
136         }
137         else if (ch==‘P‘)
138         {
139             cin>>X1>>Y1>>X2>>Y2;
140             T++;
141             f[T]=T;
142             l[T]=line(point(X1,Y1),point(X2,Y2));
143             //cout<<l[T].a.x<<" "<<l[T].a.y<<" "<<l[T].b.x<<" "<<l[T].b.y<<endl;
144             for (int j=1;j<T;j++)
145                 if (intersect_in(l[T],l[j])>0)
146                     iunion(j,T);
147         }
148     }
149
150     if (times>0)
151         cout<<endl;
152     }
153     return 0;
154 }
时间: 2025-01-07 16:07:05

hdu 1558 线段相交+并查集的相关文章

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

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐标,当输入Q的时候输入n,然后输出与第n条线段相交的线段有多少条 首先判断线段是否相交,在算法导论p577上有介绍 线段A(x1,y1)-B(x2,y2),所在直线L1方程为F1(x,y)=0;线段C(x3,y3)-D(x4,y4),所在直线L2方程为F2(x,y)=0; 如何判断两条线段有交点:(

hdu 1558 线段相交+并查集路径压缩

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3457    Accepted Submission(s): 1290 Problem Description A segment and all segments which are connected with it compose a segment set.

hdu 1558 Segment set (并查集)

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3907    Accepted Submission(s): 1471 Problem Description A segment and all segments which are connected with it compose a segment set

poj 1127 Jack Straws 线段相交+并查集

题意: 有n个木棍,给出木棍的两个端点的x,y坐标,判断其中某两个线段是否连通(可通过其他线段连通) #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <queue> #include <map> #include <

hdu 1558 Segment set (并查集+计算几何)

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3486    Accepted Submission(s): 1297 Problem Description A segment and all segments which are connected with it compose a segment set

poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)

Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are

poj1127 Jack Straws(线段相交+并查集)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Jack Straws Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3512   Accepted: 1601 Description In the game of Jack Straws, a number of plastic or wooden "straws" are dumped o

HDU 2017 Code Lock (并查集的应用+快速幂)

链接:HDU 3461 题目大意: 题目的大意是一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限次的"增加"操作后可以变成另一组密码,那么我们认为这两组密码是相同的.该题的目标就是在给定N.M和M个区间的前提下计算有多少种不同的密码. 根据题意,如果一个可调整的区间都没有的话,答案应该是26

hdu 3234 Exclusive-OR (并查集+异或性质)

Exclusive-OR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2177    Accepted Submission(s): 603 Problem Description You are not given n non-negative integers X0, X1, ..., Xn-1 less than 220 ,