poj 1127
//200k, 32ms
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAX_M = 10005;
const int MAX_N = 20;
const double EPS = 1e-10;
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); }
};
int n, m;
int a[MAX_M], b[MAX_M];
P p[MAX_N], q[MAX_N];
bool g[MAX_N][MAX_N];
//判断点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-12的交点
P intersection(P p1, P p2, P q1, P q2) {
return p1 + (p2 - p1 ) * ((q2 - q1).det(q1 - p1) / (q2 - q1).det(p2 - p1));
}
void solve() {
for(int i=0; i<n; i++) {
g[i][i] = true;
for(int j=0; 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-warshall
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];
}
}
}
}
int main() {
freopen("in.txt", "r", stdin);
while(~scanf("%d", &n)) {
if(n == 0) break;
for(int i=0; i<n; i++) {
scanf("%lf%lf%lf%lf", &p[i].x, &p[i].y, &q[i].x, &q[i].y);
}
solve();
int c, d;
while(~scanf("%d%d", &c, &d)) {
if(c==0 && d==0) break;
if(g[c-1][d-1])
printf("CONNECTED\n");
else
printf("NOT CONNECTED\n");
}
}
fclose(stdin);
return 0;
}
并查集:
//248k, 47ms
#include <iostream>
using namespace std;
/*--------- 并查集 模板 ------------*/
int UFS_NUM; //并查集中元素总数
typedef struct node{
int data; //节点对应的编号
int rank; //节点对应秩
int parent; //节点对应的双亲下标
}UFSTree; //并查集树的节点类型
void MAKE_SET(UFSTree t[]) //初始化并查集树
{
int i;
for(i=1;i<=UFS_NUM;i++){
t[i].data = i;
t[i].rank = 0;
t[i].parent = i;
}
}
int FIND_SET(UFSTree t[],int x) //在x所在的子树中查找集合编号
{
if(t[x].parent == x)
return x;
else
return FIND_SET(t,t[x].parent);
}
void UNION(UFSTree t[],int x,int y) //将x和y所在的子树合并
{
x = FIND_SET(t,x);
y = FIND_SET(t,y);
if(t[x].rank > t[y].rank)
t[y].parent = x;
else{
t[x].parent = y;
if(t[x].rank==t[y].rank)
t[y].rank++;
}
}
/*--------- 判断两线段相交 模板 ------------*/
const double eps=1e-10;
struct point { double x, y; };
double min(double a, double b) { return a < b ? a : b; }
double max(double a, double b) { return a > b ? a : b; }
bool inter(point a, point b, point c, point d){
if ( min(a.x, b.x) > max(c.x, d.x) ||
min(a.y, b.y) > max(c.y, d.y) ||
min(c.x, d.x) > max(a.x, b.x) ||
min(c.y, d.y) > max(a.y, b.y) ) return 0;
double h, i, j, k;
h = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
i = (b.x - a.x) * (d.y - a.y) - (b.y - a.y) * (d.x - a.x);
j = (d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x);
k = (d.x - c.x) * (b.y - c.y) - (d.y - c.y) * (b.x - c.x);
return h * i <= eps && j * k <= eps;
}
/*---------- 代码实现 -----------*/
struct line
{
point p1;
point p2;
};
int main()
{
int n;
UFSTree t[105];
while(cin>>n){
if(n==0) break;
UFS_NUM = n;//确定并查集树中元素总数
MAKE_SET(t); //初始化并查集
line l[15];
for(int i=1;i<=n;i++)
cin>>l[i].p1.x>>l[i].p1.y>>l[i].p2.x>>l[i].p2.y;
for(int i=1;i<=n;i++) //根据关系生成关系树
for(int j=1;j<=n;j++){
if(i==j) continue;
if(inter(l[i].p1,l[i].p2,l[j].p1,l[j].p2)){ //如果相交,有亲戚关系
UNION(t,i,j); //合并相关集合
}
}
int l1,l2;
while(cin>>l1>>l2){
if(l1==0 && l2==0)
break;
l1 = FIND_SET(t,l1);
l2 = FIND_SET(t,l2);
if(l1 == l2)
cout<<"CONNECTED"<<endl;
else
cout<<"NOT CONNECTED"<<endl;
}
}
return 0;
}