链接:点击打开链接
题意:给出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;
}