hdu 1558 Segment set
2013-08-11 21:58
190 查看
点击打开hdu 1558
思路: 计算几何+并查集
分析:
1 有n个操作,最后求有几个集合或者说是连通分量
2 对于输入一条线段我们就去前面找能够和它相交的线段,利用并查集进行合并并且更新rank数组,rank[x]数组保存的是以x为跟节点的集合的线段的数量
3 这一题难点就是线段的相交判断
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps = 1e-8;
const double INF = 1<<30;
const int MAXN = 1010;
struct Node{
double x1;
double y1;
double x2;
double y2;
};
Node node[MAXN];
int n;
int father[MAXN];
int rank[MAXN];
void init(int m){
for(int i = 0 ; i <= m ; i++){
father[i] = i;
rank[i] = 1;
}
}
int find(int x){
if(father[x] != x){
int fa = father[x];
father[x] = find(fa);
rank[x] += rank[fa];
}
return father[x];
}
double multiply1(Node a , Node b){
return (a.x1-a.x2)*(b.y1-a.y1)-(a.y1-a.y2)*(b.x1-a.x1);
}
double multiply2(Node a , Node b){
return (a.x1-a.x2)*(b.y2-a.y1)-(a.y1-a.y2)*(b.x2-a.x1);
}
bool inter(Node a , Node b){
if(max(a.x1,a.x2) >= min(b.x1,b.x2) &&
max(b.x1,b.x2) >= min(a.x1,a.x2) &&
max(a.y1,a.y2) >= min(b.y1,b.y2) &&
max(b.y1,b.y2) >= min(a.y1,a.y2) &&
multiply1(a,b) * multiply2(a,b) <= eps &&
multiply1(b,a) * multiply2(b,a) <= eps)
return true;
else return false;
}
void solve(){
for(int i = 1 ; i < n ; i++){
if(inter(node[i] , node
)){
int fx = find(i);
int fy = find(n);
if(fx != fy){
father[fy] = fx;
rank[fx] += rank[fy];
}
}
}
}
int main(){
int cas , m , k;
bool isFirst = true;
char c;
scanf("%d" , &cas);
while(cas--){
if(isFirst)
isFirst = false;
else
puts("");
n = 1;
scanf("%d%*c" , &m);
init(m);
while(m--){
c = getchar();
if(c == 'P'){
scanf("%lf" ,&node
.x1);
scanf("%lf" ,&node
.y1);
scanf("%lf" ,&node
.x2);
scanf("%lf%*c" ,&node
.y2);
if(node
.x1 > node
.x2){
swap(node
.x1 , node
.x2);
swap(node
.y1 , node
.y2);
}
solve();
n++;
}
else{
scanf("%d%*c" , &k);
int fa = find(k);
printf("%d\n" , rank[fa]);
}
}
}
return 0;
}
思路: 计算几何+并查集
分析:
1 有n个操作,最后求有几个集合或者说是连通分量
2 对于输入一条线段我们就去前面找能够和它相交的线段,利用并查集进行合并并且更新rank数组,rank[x]数组保存的是以x为跟节点的集合的线段的数量
3 这一题难点就是线段的相交判断
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps = 1e-8;
const double INF = 1<<30;
const int MAXN = 1010;
struct Node{
double x1;
double y1;
double x2;
double y2;
};
Node node[MAXN];
int n;
int father[MAXN];
int rank[MAXN];
void init(int m){
for(int i = 0 ; i <= m ; i++){
father[i] = i;
rank[i] = 1;
}
}
int find(int x){
if(father[x] != x){
int fa = father[x];
father[x] = find(fa);
rank[x] += rank[fa];
}
return father[x];
}
double multiply1(Node a , Node b){
return (a.x1-a.x2)*(b.y1-a.y1)-(a.y1-a.y2)*(b.x1-a.x1);
}
double multiply2(Node a , Node b){
return (a.x1-a.x2)*(b.y2-a.y1)-(a.y1-a.y2)*(b.x2-a.x1);
}
bool inter(Node a , Node b){
if(max(a.x1,a.x2) >= min(b.x1,b.x2) &&
max(b.x1,b.x2) >= min(a.x1,a.x2) &&
max(a.y1,a.y2) >= min(b.y1,b.y2) &&
max(b.y1,b.y2) >= min(a.y1,a.y2) &&
multiply1(a,b) * multiply2(a,b) <= eps &&
multiply1(b,a) * multiply2(b,a) <= eps)
return true;
else return false;
}
void solve(){
for(int i = 1 ; i < n ; i++){
if(inter(node[i] , node
)){
int fx = find(i);
int fy = find(n);
if(fx != fy){
father[fy] = fx;
rank[fx] += rank[fy];
}
}
}
}
int main(){
int cas , m , k;
bool isFirst = true;
char c;
scanf("%d" , &cas);
while(cas--){
if(isFirst)
isFirst = false;
else
puts("");
n = 1;
scanf("%d%*c" , &m);
init(m);
while(m--){
c = getchar();
if(c == 'P'){
scanf("%lf" ,&node
.x1);
scanf("%lf" ,&node
.y1);
scanf("%lf" ,&node
.x2);
scanf("%lf%*c" ,&node
.y2);
if(node
.x1 > node
.x2){
swap(node
.x1 , node
.x2);
swap(node
.y1 , node
.y2);
}
solve();
n++;
}
else{
scanf("%d%*c" , &k);
int fa = find(k);
printf("%d\n" , rank[fa]);
}
}
}
return 0;
}
相关文章推荐
- hdu 1558 Segment set (并查集)
- hdu 1558 Segment set(线段相交+并查集)
- HDU 1558 Segment set(线段相交+并查集)
- hdu_1558_Segment set(并查集+计算几何)
- hdu 1558 Segment set
- hdu 1558 Segment set【基础带权并查集+计算几何】
- hdu 1558 Segment set
- hdu_1558_Segment set(并查集+计算几何)
- hdu 1558 Segment set (并查集)
- hdu 1558 Segment set 线段相交+并查集
- HDU 1558 Segment set(判断线段相交+并查集)
- HDU 1558 Segment set, 计算几何+并查集
- hdu 1558 Segment set(并查集+计算几何线段相交)
- HDU-1558-Segment set
- HDU 1558 Segment set (并查集+线段相交)
- HDU 1558 Segment set 并查集加计算几何
- hdu 1558 Segment set(并查集+判断线段是否相交)
- hdu 1558 Segment set(并查集+线段相交)
- HDU--1558--Segment set--并查集***经典***
- HDU 1558 Segment set (并查集+线段非规范相交)