【题意】给你一些线段,求出哪些线段是相连的,哪些是不相连的。相连包括间接相连,即这两条线段本身不直接相连,而是通过其它线段的连接而间接相连。
【解题方法】
解决这道题目的关键要解决两个问题:1.判断两条线段是否直接相连,即它们相交与否,这是一个几何问题;2.如果某两条线段不相交,那么它们是否通过其它线段的连接而间接相连。这个地方方法可以用并查集,也可以用Floyd-Warshall算法,我选择后者!
【AC 代码】
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps=1e-10;
const int maxn=20;
const int maxm=10010;
//考虑有误差的加法运算
double add(double a,double b)
{
if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return 0;
return a+b;
}
//二维向量结构体
struct P{
double x,y;
P(){}
P(double x,double y):x(x),y(y){}
P operator +(P p){
return P(add(x,p.x),add(y,p.y));
}
P operator -(P p){
return P(add(x,-p.x),add(y,-p.y));
}
P operator *(double d){
return P(x*d,y*d);
}
double dot(P p){ //内积
return add(x*p.x,y*p.y);
}
double det(P p){//差集
return add(x*p.y,-y*p.x);
}
};
//判断点q是否在线段p1-p2上
bool on_seg(P p1,P p2,P q){
return (p1-q).det(p2-q)==0&&(p1-q).dot(p2-q)<=0;
}
//计算p1-p2与直线q1-q2的交点
P intersection(P p1,P p2,P q1, P q2){
return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
//输入
int n;
P p[maxn],q[maxn];
int m;
int a[maxm],b[maxm];
bool g[maxn][maxn]; //相连关系图
int main()
{
while(~scanf("%d",&n)&&n)
{
for(int i=0; i<n; i++) scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y);
m=0;
int x,y;
while(scanf("%d%d",&x,&y)){
if(x==0&&y==0) break;
a[m]=x,b[m]=y;
m++;
}
for(int i=0; i<n; i++){
g[i][i]=true;
for(int j=0; j<i; j++){
//判断木棍i和木棍j是否有公共交点
if((p[i]-q[i]).det(p[j]-q[j])==0){
//平行时,检查端点
g[i][j]=g[j][i]=on_seg(p[i],q[i],p[j])||
on_seg(p[i],q[i],q[j])||
on_seg(p[j],q[j],p[i])||
on_seg(p[j],q[j],q[i]);
}else{
//非平行时
P r=intersection(p[i],q[i],p[j],q[j]);
g[i][j]=g[j][i]=on_seg(p[i],q[i],r)&&on_seg(p[j],q[j],r);
}
}
}
//通过Floyd算法判断任意两点是否相连
for(int k=0; k<n; k++){
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
g[i][j]|=g[i][k]&&g[k][j];
}
}
}
for(int i=0; i<m; i++){
puts(g[a[i]-1][b[i]-1]?"CONNECTED":"NOT CONNECTED");
}
}
}