以POJ1127作为例题分析模板
/**
题意: 这道题目问的是:给你一些线段,求出哪些线段是相连的,哪些是不相连的。相连包括间接相连,
即这两条线段本身不直接相连,而是通过其它线段的连接而间接相连。解决这道题目的关键要解决两个问题:
1.判断两条线段是否直接相连,即它们相交与否,这是一个几何问题;
2.如果某两条线段不相交,那么它们是否通过其它线段的连接而间接相连。如果把相连的线段看做是一个集合,
这个问题变成判断这两条线段是否处于同一个集合中,我们可以用并查集这个数据结构去解决这个问题。
关键:判断两个线段是否有交点(交点在线段上) 有两个思路
1.快速排斥试验和跨立试验
/**
bool isIntersect(Point p1,Point p2,Point q1,Point q2)
{
///快速排斥 - 两条线段所构成的矩形有相交
if(max(p1.x,p2.x)<min(q1.x,q2.x)||max(q1.x,q2.x)<min(p1.x,p2.x)||max(p1.y,p2.y)<min(q1.y,q2.y)||max(q1.y,q2.y)<min(p1.y,p2.y))
return 0;
///跨立试验 如果 p1p2 跨立 q1q2 则 p1-q1,p2-q1一定在q2 - q1两侧 同理 q1-p1,q2-p1 在 p2 - p1 两侧
if(dot(q2 - q1,p1 - q1)*dot(q2 - q1,p2 - q1)<=0 && dot(p2 - p1,q1 - p1)*dot(p2 - p1,q2 - p1)<=0)
return 1;
else
return 0;
}
2.求交点,判断交点在两条线段上 || 平行的时候要特殊判断是否有重合
/**
if(平行) // 两条线段向量 det 外积 == 0
{
特殊判断下是否存在重合
bool flag = online(ben[i].a,ben[j])||online(ben[i].b,ben[j])||online(ben[j].a,ben[i])||online(ben[j].b,ben[i]);
return flag;
}
else //相交
{
通过等分定理利用外积求出的面积比=线段比 => 交点
判断交点是否同时满足在两条线段上online(交点,line a) && online(交点,line b);
}
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps = 1e-10;
const double pi = acos(-1.0);
int cmp(double x,double b)
{
if(fabs(x - b) < eps) return 0;
if(x > b) return 1;
return -1;
}
struct point
{
double x,y;
point() {}
point(double a,double b):x(a),y(b){}
void input() {
scanf("%lf%lf",&x,&y);
}
friend point operator + (const point &a,const point &b){
return point(a.x+b.x,a.y+b.y);
}
friend point operator - (const point &a,const point &b){
return point(a.x-b.x,a.y-b.y);
}
friend bool operator == (const point &a,const point &b){
return !cmp(a.x,b.x) && !cmp(a.y,b.y);
}
friend point operator * (const point &a,const double &b){
return point(a.x*b,a.y*b);
}
friend point operator * (const double &a,const point &b){
return point(a*b.x,a*b.y);
}
friend point operator / (const point &a,const double &b){
return point(a.x/b,a.y/b);
}
double norm() {
return sqrt(x*x + y*y);
}
};
double det(const point &a,const point &b)
{
return a.x * b.y - a.y * b.x;
}
double dot(const point &a,const point &b)
{
return a.x*b.x + a.y*b.y;
}
double dist(const point &a,const point &b)
{
return (a - b).norm();
}
point rotate_point(const point &p,double angle)
{
double tx = p.x,ty = p.y;
return point(tx * cos(angle) - ty * sin(angle),tx * sin(angle) + ty * cos(angle));
}
struct line
{
point a,b;
line() {}
line(point x,point y):a(x),b(y){}
void input(){
a.input();
b.input();
}
};
line point_make_line(const point &a,const point &b)
{
return line(a,b);
}
double dis_point_segment(const point &p,const line &s)
{
if(cmp(dot(p-s.a,s.b-s.a),0) < 0) return dist(p,s.a);
if(cmp(dot(p-s.b,s.a-s.b),0) < 0) return dist(p,s.b);
return fabs(det(s.a-p,s.b-p) / dist(s.a,s.b));
}
void pointprojline(const point &p,const line &s,point &cp)
{
double r = dot(p-s.a,s.b-s.a) / dot(s.b-s.a,s.b-s.a);
cp = s.a + r * (s.b - s.a);
}
bool pointonsegment(const point &p,const line &s)
{
return cmp(det(p-s.a,s.b-s.a),0) == 0 && cmp(dot(p-s.a,p-s.b),0) <=0;
}
bool parallel(const line &x,const line &y)
{
return !cmp(det(x.a - x.b,y.a - y.b),0);
}
bool line_make_point(const line &x,const line &y,point &res)
{
if(parallel(x,y)) return false;
double s1 = det(x.a - y.a,y.b - y.a);
double s2 = det(x.b - y.a,y.b - y.a);
res = (s1 * x.b - s2 * x.a) / (s1 - s2);
return true;
}
line move_d(const line &x,const double &len)
{
point d = x.b - x.a;
d = d / d.norm();
d = rotate_point(d,pi / 2);
return line(x.a + d * len,x.b + d * len);
}
const int maxn = 20;
line ben[maxn];
/// Union find
int pnt[maxn],urank[maxn];
void initunion() {
memset(pnt,0,sizeof(pnt));
memset(urank,0,sizeof(urank));
for(int i=0;i<maxn;i++) pnt[i] = i , urank[i] = 0;
}
int ufind(int x) {
if(x!=pnt[x]) pnt[x] = ufind(pnt[x]);
return pnt[x];
}
void umerge(int x,int y) {
if(urank[x = ufind(x)] > urank[ y = ufind(y) ]) pnt[y] = x;
else {
pnt[x] = y;
urank[y] += (urank[x] == urank[y]);
}
}
int main()
{
int n;
while(~scanf("%d",&n),n)
{
initunion();
memset(ben,0,sizeof(ben));
for(int i=1;i<=n;i++) ben[i].input();
point temp;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(line_make_point(ben[i],ben[j],temp) && pointonsegment(temp,ben[i]) && pointonsegment(temp,ben[j]))
umerge(i,j);
else {
bool flag = pointonsegment(ben[i].a,ben[j]) || pointonsegment(ben[i].b,ben[j])
||pointonsegment(ben[j].a,ben[i]) || pointonsegment(ben[j].b,ben[i]);
if(flag) umerge(i,j);
}
}
}
int u,v;
while(scanf("%d%d",&u,&v),u+v)
{
u = ufind(u);
v = ufind(v);
if ( u == v) cout<<"CONNECTED"<<endl;
else cout<<"NOT CONNECTED"<<endl;
}
}
return 0;
}