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;

如何判断两条线段有交点:(A,B在直线L2两侧) AND (C,D在直线L1两侧)。

用数学表达式来表示可以这样来表示:F2(x1,y1)*F2(x2,y2) >= 0 AND F1(x3,y3)*F1(x4,y4)>= 0; 等于0表示恰好在直线上

然后就是基础的并查集判断是否在一个集合以及集合内的线段的个数

 1 #include<cstdio>
 2 using namespace std;
 3 int father[1001],num[1001];
 4 void give()
 5 {
 6     for (int i=1;i<=1000;i++)
 7     {
 8         father[i]=i;
 9         num[i]=1;
10     }
11 }
12 int _find(int x)
13 {
14     if (father[x]==x) return father[x];
15     father[x]=_find(father[x]);
16     return father[x];
17 }
18 double x1[1001],x2[1001],y1[1001],y2[1001];
19 double a[1001],b[1001];
20 int main()
21 {
22     int t,n,sx,sy,k,i,q;
23     char op;
24     scanf("%d",&t);
25         while (t--)
26         {
27             scanf("%d",&n);
28             give();k=1;
29             while (n--)
30             {
31                 scanf(" %c",&op);
32                 if (op==‘P‘)
33                 {
34                     scanf("%lf %lf %lf %lf",&x1[k],&y1[k],&x2[k],&y2[k]);
35                     a[k]=(y2[k]-y1[k])/(x2[k]-x1[k]);
36                     b[k]=(x2[k]*y1[k]-x1[k]*y2[k])/(x2[k]-x1[k]);
37                     for (i=1;i<k;i++)
38                     {
39                         int t1=0,t2=0;
40                         if (!((a[k]*x1[i]-y1[i]+b[k])*(a[k]*x2[i]-y2[i]+b[k])>0))
41                             t1=1;
42                         if (!((a[i]*x1[k]-y1[k]+b[i])*(a[i]*x2[k]-y2[k]+b[i])>0))
43                             t2=1;
44                         if (t1==1&&t2==1)
45                         {
46                             sx=_find(k);
47                             sy=_find(i);
48                             if (sx!=sy){
49                             father[sx]=sy;
50                             num[sy]+=num[sx];
51                             }
52                         }
53                     }
54                     k++;
55                 }
56                 else
57                 {
58                     scanf("%d",&q);
59                     printf("%d\n",num[_find(q)]);
60                 }
61             }
62             if (t) printf("\n");
63         }
64     return 0;
65 }
时间: 2024-10-12 09:37:17

hdu 1558 (线段相交+并查集) Segment set的相关文章

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 线段相交+并查集

题意:要求相交的线段都要塞进同一个集合里 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 #def

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

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

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 ,

HDU 4496 D-City (并查集)

题意:给你n个点m条边,问删除前i条边后有多少个连通分块. 思路:从后往前操作,从后往前添加i条边等于添加完m条边后删掉前m-i条边,可知刚开始没有边,所以sum[m]=n; #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #define M 100010

UVALive 4730 Kingdom 线段树+并查集

题目链接:点击打开链接 题意见白书P248 思路: 先把读入的y值都扩大2倍变成整数 然后离散化一下 用线段树来维护y轴 区间上每个点的 城市数量和联通块数量, 然后用并查集维护每个联通块及联通块的最大最小y值,还要加并查集的秩来记录每个联通块的点数 然后就是模拟搞.. T^T绝杀失败题..似乎数组开小了一点就过了,== #include<stdio.h> #include<math.h> #include<vector> #include<string.h>