【题目链接】 http://poj.org/problem?id=1127
【题目大意】
在二维平面中,给出一些木棍的左右端点,当木棍相交或者间接相交时
我们判断其连通,给出一些询问,问某两个木棍是否连通
【题解】
我们首先记录直接相连的木棍,然后对图跑一遍floyd算法,就能预处理出所有答案。
【代码】
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> using namespace std; 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);} //叉积 }; //判断点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-q2的交点 P intersection(P p1,P p2,P q1,P q2){ return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1)); } const int MAX_N=12; const int MAX_M=10000; int n,m; P p[MAX_N],q[MAX_N]; int a[MAX_M],b[MAX_M]; bool g[MAX_N][MAX_N]; void solve(){ memset(g,0,sizeof(g)); for(int i=0;i<n;i++){ g[i][i]=1; for(int j=0;j<i;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); } } } 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]; } } } for(int i=0;i<m;i++){ puts(g[a[i]-1][b[i]-1]?"CONNECTED":"NOT CONNECTED"); } } bool init(){ scanf("%d",&n); if(n==0)return 0; for(int i=0;i<n;i++)scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y); int x,y; m=0; while(scanf("%d%d",&x,&y),x&&y){ a[m]=x,b[m++]=y; }return 1; } int main(){ while(init())solve(); return 0; }