并查集 HDU1558

  1 #include <iostream>
  2 #include <set>
  3 #include <cstring>
  4 #include <cstdio>
  5
  6 using namespace std;
  7
  8 struct point
  9 {
 10     double x, y;
 11     point( double _x = 0, double _y = 0 )
 12     {
 13         x = _x;
 14         y = _y;
 15     }
 16     point operator-( point t )
 17     {
 18         return point( x - t.x, y - t.y );
 19     }
 20     double operator*( point t )
 21     {
 22         return x * t.y - y * t.x;
 23     }
 24 };
 25
 26 //快速排斥试验模板
 27 bool quickExclude( point a, point b, point c, point d )
 28 {
 29     int x1 = a.x, x2 = b.x, x3 = c.x, x4 = d.x;
 30     int y1 = a.y, y2 = b.y, y3 = c.y, y4 = d.y;
 31     if (  min(x1,x2) <= max(x3,x4) && min(x3,x4) <= max(x1,x2) &&
 32            min(y1,y2) <= max(y3,y4) && min(y3,y4) <= max(y1,y2)      )
 33            return true;
 34     else    return false;
 35 }
 36
 37 //跨立试验模板(两线段(ab)和(cd)是否相交)
 38 bool ifIntersect( point a, point b, point c, point d )
 39 {
 40     if ( quickExclude( a, b, c, d ) )
 41     {
 42         if (  ( ( a - c ) * ( c - d ) ) * ( ( b - c ) * ( c - d ) ) <= 0 && ( ( c - a ) * ( a - b ) ) * ( ( d - a ) * ( a - b ) ) <= 0  )
 43         return true;
 44     }
 45     return false;
 46 }
 47
 48 set<int> ss;
 49 int father[1010];
 50 int num[1010];
 51 point arr[1010][2];
 52
 53 int main()
 54 {
 55     int T;
 56     cin>>T;
 57     for(int y=0;y<T;y++)
 58     {
 59         if(y!=0)
 60             cout<<endl;
 61         int n;
 62         for(int i=1;i<=1000;i++)
 63             father[i]=i;
 64         for(int i=1;i<=1000;i++)
 65             num[i]=1;
 66         cin>>n;
 67         int time=1;
 68         char c;
 69         double x1,y1,x2,y2;
 70         for(int i=0;i<n;i++)
 71         {
 72             ss.clear();
 73             cin>>c;
 74             if(c==‘P‘)
 75             {
 76                 cin>>x1>>y1>>x2>>y2;
 77                 arr[time][0].x=x1;
 78                 arr[time][0].y=y1;
 79                 arr[time][1].x=x2;
 80                 arr[time][1].y=y2;
 81                 for(int t=1;t<time;t++)
 82                 {
 83                     if(ifIntersect(arr[time][0],arr[time][1],arr[t][0],arr[t][1]))
 84                     {
 85                         ss.insert(time);
 86                         int ft=t;
 87                         while(ft!=father[ft])
 88                         {
 89                             ft=father[ft];
 90                         }
 91                         father[ft]=time;
 92                         if(ss.find(ft)==ss.end())
 93                         {
 94                             ss.insert(ft);
 95                             num[time]=num[time]+num[ft];
 96                             num[ft]=0;
 97                         }
 98                     }
 99                 }
100                 time++;
101             }
102             else if(c==‘Q‘)
103             {
104                 int se;
105                 cin>>se;
106                 int fse=se;
107                 while(fse!=father[fse])
108                 {
109                     fse=father[fse];
110                 }
111                 int j=se;
112                 while(j!=fse)
113                 {
114                     int tmp=father[j];
115                     father[j]=fse;
116                     j=tmp;
117                 }
118                 cout<<num[fse]<<endl;
119             }
120         }
121     }
122     return 0;
123 }

时间: 2024-12-29 09:17:31

并查集 HDU1558的相关文章

HDU1558 - Segment set 并查集 + 判断线段相交

HDU1558 - Segment set: http://acm.hdu.edu.cn/showproblem.php?pid=1558 题目大意: 输入一些线段的端点坐标,若两线段相交,则把他们合并成一个集合,输入数据里会有k,问和k线段相交的线段的数目(包括自己) 思路: 每次输入一条线段,都从头扫描一次. 找出之前输入的线段里面,所有和其相交的线段,并且合并(合并用的是线段的ID). 就是: 并查集 + 判断线段相交 代码: #include <iostream> #include &

HDU HDU1558 Segment set(并查集+判断线段相交)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1558 解题报告:首先如果两条线段有交点的话,这两条线段在一个集合内,如果a跟b在一个集合内,b跟c在一个集合内,那么a跟c在一个集合内.在一个平面上,有两种操作: P:在这个平面上添加一条线段 Q k:询问添加的第k条线段所在的那个集合有多少条线段 用并查集,然后就是要判断一下线段有没有交点.还有就是题目要求两个test之间要有空行,为此我还PE了一次. 1 #include<cstdio> 2

并查集练习1

举头望明月,低头敲代码... 推荐学习地址:http://www.cnblogs.com/cyjb/p/UnionFindSets.html 简单: hdu1213 How Many Tables:新手必秒 1 #include<cstdio> 2 const int N=1001; 3 int f[N]; 4 void init(int n){ 5 for(int i=1;i<=n;++i) 6 f[i]=i; 7 } 8 int fin(int x){ 9 if(x!=f[x])f[

并查集知识学习

(转) 并查集的作用:并和查,即合并和查找,将一些集合合并,快速查找或判断某两个集合的关系,或某元素与集合的关系,或某两个元素的关系. 并查集的结构:并查集主要操作对象是森林,树的结构赋予它独特的能力,对整个集合操作转换为对根节点(或称该集合的代表元素)的操作,一个集合里的元素关系不一定确定,但相对于根节点的关系很明了,这也是为了查找方便. 并查集优化方法:按秩合并和路径压缩的配合使用,使得查找过程优化到极致.按秩合并,每次将深度小的树合并到深度大的树里面去,使得整棵树尽量矮:路径压缩,将当前节

CodeForces 745C Hongcow Builds A Nation 并查集

题意: 给了你n个城市 m条边 k个政府 每个政府管辖的区域内不能和其他政府的区域有相连 即政府之间不存在路径 问你在维护这种关系的同时 最多再加多少条边 思路: 先找出来每个联通块 再找出来没有归属的孤立的点 把他们都放到最大的联通块里 然后每个联通块之间的点两两连边是n*(n-1)/2条边 最后算出来的ans-m就好了 (看别人的博客学了一个max_element 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a

并查集(个人模版)

并查集: 1 int find(int a) 2 { 3 int r=a; 4 while(f[r]!=r) 5 r=f[r]; 6 int i=a; 7 int j; 8 while(i!=r) 9 { 10 j=f[i]; 11 f[i]=r; 12 i=j; 13 } 14 return r; 15 } 16 int merge(int a,int b) 17 { 18 int A,B; 19 A=find(a); 20 B=find(b); 21 if(A!=B) 22 { 23 f[B

并查集应用

题目描述: One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls

【bzoj3674】 可持久化并查集加强版

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 (题目链接) 题意 维护并查集3个操作:合并:回到完成第k个操作后的状态:查询. Solution 其实就是用主席树的叶子节点维护并查集的可持久化数组fa[]. 细节 终于认识到了按秩合并的强大,单纯写个路径压缩Re飞,写了路径压缩+按秩合并比单纯的按秩合并每快多少→_→ 代码 // bzoj3674 #include<algorithm> #include<iostream>

BZOJ1015[JSOI2008]星球大战starwar[并查集]

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5253  Solved: 2395[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重