题目链接:http://poj.org/problem?id=1127
题意:给你n个线段,每个线段给你两个端点的坐标。然后随意问你两个线段是否相交,线段交可以传递。
解题心得:一个线段可以用向量表示,然后用向量求交的方法得到交点,再判断交点是否在两个线段上。当两个线段平行时直接判断两个线段的端点是否在另一个线段上。
#include <cstring>
#include <stdio.h>
using namespace std;
const int maxn = 200;
const double eps = 1e-10;
double abs(double x) {//abs出问题了,哭死,重载之后就过了
if(x < 0)
return -x;
return x;
}
double add(double a, double b) {//考虑误差的加法运算
if(abs(a + b) < eps * (abs(a) + abs(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);
}
};
bool on_seg(P p1, P p2, P q) {//判断q是否在p1,p2之间
return (p1 - q).det(p2 - q) == 0 && (p1 - q).dot(p2 - q) <= 0;
}
P intersection(P p1, P p2, P q1, P q2) {//得到p2-p1向量和q1-q2的交点坐标
return p1 + (p2 - p1) * ((q2 - q1).det(q1 - p1) / (q2 - q1).det(p2 - p1));
}
P q[maxn], p[maxn];//p记录线段左边的坐标,q记录线段右边的坐标
//并查集用来检查线段交的传递
int father[maxn];
int find(int x) {
if(father[x] == x) return x;
else return father[x] = find(father[x]);
}
void merge(int x,int y) {
int fx = find(x);
int fy = find(y);
if(fx != fy) father[fx] = fy;
}
int main() {
// freopen("1.in", "r", stdin);
int n;
while(scanf("%d", &n)!= EOF && n) {
for(int i=1;i<=n;i++) {
scanf("%lf%lf%lf%lf", &p[i].x, &p[i].y, &q[i].x, &q[i].y);
father[i] = i;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j < i; j++) {
if ((p[i] - q[i]).det(p[j] - q[j]) == 0) {//如果两个线段平行
if (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])) {
merge(i, j);
}
} else {
P r = intersection(p[i], q[i], p[j], q[j]);//得到两个向量的交点
if (on_seg(p[i], q[i], r) && on_seg(p[j], q[j], r))//查看这个交点是否在两个线段上
merge(i, j);
}
}
}
int a, b;
while (scanf("%d%d", &a, &b) && a + b) {
if (find(a) == find(b)) puts("CONNECTED");
else puts("NOT CONNECTED");
}
}
return 0;
}