poj1127

链接:点击打开链接

题意:给出m对木棍的两个端点坐标,如果两根木棍有公共点则认为两根木棍相交,通过相连木棍间接连在一起的木棍也认为是相连的

代码1:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
    double stx,sty;
    double enx,eny;
};
double cross1(node p,node q){
     return (p.stx-p.enx)*(q.sty-p.sty)-(p.sty-p.eny)*(q.stx-p.stx);
}
double cross2(node p,node &q){
     return (p.stx-p.enx)*(q.eny-p.sty)-(p.sty-p.eny)*(q.enx-p.stx);
}
int judge(node p,node q){
     if(max(p.stx,p.enx)>=min(q.stx,q.enx)&&
     max(q.stx,q.enx)>=min(p.stx,p.enx)&&
     max(p.sty,p.eny)>=min(q.sty,q.eny)&&
     max(q.sty,q.eny)>=min(p.sty,p.eny)&&
     cross1(p,q)*cross2(p,q)<=0&&
     cross1(q,p)*cross2(q,p)<=0)
     return 1;
     return 0;
}                                               //通过快速排斥和跨立实验判断线段相交
int par[50],ran[50];
int find(int x){
    if(x==par[x])
    return x;
    return par[x]=find(par[x]);
}
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y)
    return;
    if(ran[x]<ran[y])
    par[x]=y;
    else{
        par[y]=x;
        if(ran[x]==ran[y])
        ran[x]++;
    }
}
bool same(int x,int y){
    return find(x)==find(y);
}
int main(){
    int n,i,j,x,y;
    node tmp,p[50];
    while(scanf("%d",&n)!=EOF&&n){
        memset(ran,0,sizeof(ran));
        for(i=1;i<=n;i++)
        par[i]=i;
        for(i=1;i<=n;i++)
        scanf("%lf%lf%lf%lf",&p[i].stx,&p[i].sty,&p[i].enx,&p[i].eny);
        for(i=1;i<=n;i++)
        for(j=i+1;j<=n;j++)
        if(judge(p[i],p[j]))                    //用并查集维护
        unite(i,j);
        while(scanf("%d%d",&x,&y)&&(x||y)){
            if(same(x,y))
            puts("CONNECTED");
            else
            puts("NOT CONNECTED");
        }
    }
    return 0;
}


代码2:

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const double EPS=1e-10;
double add(double a,double b){
    if(fabs(a+b)<EPS*(fabs(a)+fabs(b)))
    return 0;
    return a+b;
}
struct node{
    double x,y;
    node(){}
    node(double x,double y):x(x),y(y){}
    node operator+(node p){
    return node(add(x,p.x),add(y,p.y));
    }
    node operator-(node p){
    return node(add(x,-p.x),add(y,-p.y));
    }
    node operator*(double d){
    return node(x*d,y*d);
    }
    double N(node p){
    return add(x*p.x,y*p.y);
    }
    double W(node p){
    return add(x*p.y,-y*p.x);
    }
};
bool on_seg(node p1,node p2,node p){
    return (p1-p).N(p2-p)<=0;
}
node cal(node p1,node p2,node q1,node q2){
    return p1+(p2-p1)*((q2-q1).W(q1-p1)/(q2-q1).W(p2-p1));
}
int par[50],ran[50];
int find(int x){
    if(x==par[x])
    return x;
    return par[x]=find(par[x]);
}
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y)
    return;
    if(ran[x]<ran[y])
    par[x]=y;
    else{
        par[y]=x;
        if(ran[x]==ran[y])
        ran[x]++;
    }
}                                               //通过外积和内积求出直线交点,再判断是否是线段交点
bool same(int x,int y){
    return find(x)==find(y);
}
int main(){
    int n,i,j,x,y;
    node tmp,p[50],q[50];
    while(scanf("%d",&n)!=EOF&&n){
        memset(ran,0,sizeof(ran));
        for(i=1;i<=n;i++)
        par[i]=i;
        for(i=1;i<=n;i++)
        scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y);
        for(i=1;i<=n;i++)
        for(j=i+1;j<=n;j++){
            if((p[i]-q[i]).W(p[j]-q[j])==0){    //平行时可能会重合单独考虑
                if(on_seg(p[i],q[i],p[j])||on_seg(p[i],q[i],q[j])){
                unite(i,j);
                }
            }
            else{
                tmp=cal(p[i],q[i],p[j],q[j]);
                if(on_seg(p[i],q[i],tmp)&&on_seg(p[j],q[j],tmp)){
                unite(i,j);
                }
            }
        }
        while(scanf("%d%d",&x,&y)&&(x||y)){
            if(same(x,y))
            puts("CONNECTED");
            else
            puts("NOT CONNECTED");
        }
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值