本题是处理线段是否相交的题目。
题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=1102
判断两条线段是否相交的模板如下:
const double eps = 1e-8;
struct Point
{
int x;
int y;
Point() {}
Point(int _x,int _y):x(_x),y(_y) {}
friend Point operator + (Point a,Point b)
{
return Point(a.x+b.x , a.y+b.y);
}
friend Point operator - (Point a,Point b)
{
return Point(a.x-b.x , a.y-b.y);
}
};
int dcmp(double x) //三态函数
{
if(fabs(x)<eps)//在一定的精度范围内可认为是0
return 0;
return x>0?1:-1;
}
double det(Point a,Point b) // 叉积,重载叉积函数
{
return a.x*b.y-a.y*b.x;
}
double det(Point a,Point b,Point o) // 叉积
{
return det(a-o,b-o);
}
double det(Point a,Point b,Point c,Point d) // 叉积
{
return det(b-a,d-c);
}
double dot(Point a,Point b) // 点积
{
return a.x*b.x + a.y*b.y;
}
double dot(Point a,Point b,Point o) // 点积
{
return dot(a-o,b-o);
}
bool intersect(Point a,Point b,Point c,Point d)// 判断线段是否相交
{
int d1 = dcmp( det(a,b,c) );
int d2 = dcmp( det(a,b,d) );
int d3 = dcmp( det(c,d,a) );
int d4 = dcmp( det(c,d,b) );
if((d1*d2<0&&d3*d4<0))
return true;
else if(d1==0&&dot(a,b,c)<=0)
return true;
else if(d2==0&&dot(a,b,d)<=0)
return true;
else if(d3==0&&dot(c,d,a)<=0)
return true;
else if(d4==0&&dot(c,d,b)<=0)
return true;
else return false;
}
但对于本题而言,除了两条线段直接相交外,也可能间接相交。可以用Floyed来进行闭包的传递,当然也可以用并查集。
代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
using namespace std;
const double eps = 1e-8;
struct Point
{
int x;
int y;
Point() {}
Point(int _x,int _y):x(_x),y(_y) {}
friend Point operator + (Point a,Point b)
{
return Point(a.x+b.x , a.y+b.y);
}
friend Point operator - (Point a,Point b)
{
return Point(a.x-b.x , a.y-b.y);
}
};
struct Edge
{
Point a;
Point b;
};
Edge e[15];
bool map[15][15];
int dcmp(double x) //三态函数
{
if(fabs(x)<eps)//在一定的精度范围内可认为是0
return 0;
return x>0?1:-1;
}
double det(Point a,Point b) // 叉积,重载叉积函数
{
return a.x*b.y-a.y*b.x;
}
double det(Point a,Point b,Point o) // 叉积
{
return det(a-o,b-o);
}
double det(Point a,Point b,Point c,Point d) // 叉积
{
return det(b-a,d-c);
}
double dot(Point a,Point b) // 点积
{
return a.x*b.x + a.y*b.y;
}
double dot(Point a,Point b,Point o) // 点积
{
return dot(a-o,b-o);
}
bool intersect(Point a,Point b,Point c,Point d)// 判断线段是否相交
{
int d1 = dcmp( det(a,b,c) );
int d2 = dcmp( det(a,b,d) );
int d3 = dcmp( det(c,d,a) );
int d4 = dcmp( det(c,d,b) );
if((d1*d2<0&&d3*d4<0))
return true;
else if(d1==0&&dot(a,b,c)<=0)
return true;
else if(d2==0&&dot(a,b,d)<=0)
return true;
else if(d3==0&&dot(c,d,a)<=0)
return true;
else if(d4==0&&dot(c,d,b)<=0)
return true;
else return false;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n;
while(scanf("%d",&n)!=EOF && n!=0)
{
for(int i=1; i<=n; i++)
{
scanf(" %d %d %d %d",&e[i].a.x,&e[i].a.y,&e[i].b.x,&e[i].b.y);
}
memset(map,0,sizeof(map));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
//如果两条边相交
if(i!=j && intersect(e[i].a,e[i].b,e[j].a,e[j].b))
{
map[i][j] = true;
}
}
}
//用Floyed处理
for(int k = 1; k<=n; k++)
{
for(int i = 1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(map[i][k] == true && map[k][j] == true)
{
map[i][j] = true;
}
}
}
}
int a,b;
while(scanf(" %d %d",&a,&b) == 2 && (a!=0 || b!=0))
{
if(a == b || map[a][b] == true)
{
printf("CONNECTED\n");
}
else
{
printf("NOT CONNECTED\n");
}
}
}
return 0;
}