题意:给你n条线段,编号从1到n,然后判断两个线段(输入以0,0结束)是否相连(间接相连也算相连)。
分析:
公式:p1*p2=(x1*x2,y1*y2)(内积),p1xp2=(x1*y2,x2*y1)(外积)
判断q是否在线段p1-p2上面,根据(p1-q)x(p2-q)=0来判断q是否在直线p1-p2上。利用内积(p1-q)*(p2-q)<0判断q是否在p1-p2之间。p1-p2,q1-q2的交点:
(x,y)=p1+(p2-p1)*((q2-q1)x(q1-p1)/((q2-q1)x(p2-p1)));
并查集:由于数据太小,可以不用并查集,随便写写就好。
#include <iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define EPS 1e-10
#define N 105
struct point
{
double a,b;
point(){}
point(double a,double b):a(a),b(b){}
point operator +(point p)
{
return point(p.a+a,p.b+b);
}
point operator -(point p)
{
return point(a-p.a,b-p.b);
}
point operator *(double p)
{
return point(a*p,b*p);
}
double dot(point p)//内积
{
return (p.a*a+p.b*b);
}
double det(point p)//外积
{
return (a*p.b-b*p.a);
}
};
point p1[N],p2[N];
//判断q是否在线段p1-p2上
bool on_str(point p1,point p2,point q)
{
return (abs((p1-q).det(p2-q))<EPS&&(p1-q).dot(p2-q)<EPS);
}
//求两直线交点
point intersection(point p1,point p2,point q1,point q2)
{
return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
bool judge(int i,int j)
{
if(abs((p1[i]-p2[i]).det(p1[j]-p2[j]))<EPS)
{
if(on_str(p1[i],p2[i],p1[j])||on_str(p1[i],p2[i],p2[j])||on_str(p1[j],p2[j],p1[i])||on_str(p1[j],p2[j],p2[i]))//判断是否有重合
return 1;
else
return 0;
}
point r=intersection(p1[i],p2[i],p1[j],p2[j]);
return on_str(p1[i],p2[i],r)&&on_str(p1[j],p2[j],r);
}
int myrank[N],par[N];
void init(int n)
{
for(int i=0;i<n;i++)
{
myrank[i]=0;
par[i]=i;
}
}
int myfind(int x)
{
if(par[x]==x)
return x;
return par[x]=myfind(par[x]);
}
void unite(int x,int y)
{
x=myfind(x);
y=myfind(y);
if(x==y)return;
if(myrank[x]<myrank[y])
{
par[x]=y;
}
else
{
par[y]=x;
if(myrank[x]==myrank[y])
myrank[x]++;
}
}
bool same(int x,int y)
{
return myfind(x)==myfind(y);
}
int main()
{
int n;
while(scanf("%d",&n)&&n)
{
init(n);
for(int i=0;i<n;i++){
scanf("%lf%lf%lf%lf",&p1[i].a,&p1[i].b,&p2[i].a,&p2[i].b);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
if(judge(i,j))
{
unite(i,j);
}
}
}
int a,b;
while(~scanf("%d%d",&a,&b)&&(!(a==0&&b==0)))
{
if(same(a-1,b-1))
printf("CONNECTED\n");
else
printf("NOT CONNECTED\n");
}
}
return 0;
}