1. 程式人生 > >POJ1127 Jack Straws

POJ1127 Jack Straws

alt bool span img lse div -a height turn

給你一些線段,求出哪些線段是相連的,哪些是不相連的。相連包括間接相連,即這兩條線段本身不直接相連,而是通過其它線段的連接而間接相連。

線段相交+並查集

這裏主要說如何判斷線段相交:快速排斥試驗+跨立試驗
牢記一點:研究對象一定是兩條線段的四個端點

技術分享圖片

(快速排斥試驗:只是可以證明這兩條一定不相交,達到一點加速效果)
以線段P1,P2為對角線作一矩形R,再以Q1,Q2為對角線作矩形T,當兩個矩形不相交的時候兩條線段肯定不相交,即線段相交的必要條件時矩形相交。
矩陣相交依據:兩條線段一共四個端點,x/y軸中,最小的兩個端點不能屬於同一條線段
min(p1.x,p2.x)<=max(q1.x,q2.x)&&

min(q1.x,q2.x)<=max(p1.x,p2.x)&&
min(p1.y,p2.y)<=max(q1.y,q2.y)&&
min(q1.y,q2.y)<=max(p1.y,p2.y)

技術分享圖片


(跨立試驗:叉乘+點乘,保證一條線段的兩端點在另一條線段的兩側)
(Q1P1xQ1Q2)*(Q1Q2xQ1P2)>0
(P1Q1xP1P2)*(P1Q2xP1P2)>0
叉乘公式:
a x b=(l,m,n)x(o,p,q)=((mq-pn),(no-lq),(lp-mo))
平面的話 a x b=(a.x,a.y,0)x(b.x,b.y,0)=(0,0,a.x*b.y-a.y-b.x)

上代碼:

struct point{
int x,y;
};
struct seg{
point a,b;
}S;

int mul(point p1,p2,p3){
return (p1.x-p2.x)*(p3.y-p2.y)-(p1.y-p2.y)*(p3.x-p2.x);
}

bool insect(point p1,p2,q1,q2){
if(max(p1.x,p2.x)<min(q1.x,q2.x)||max(q1.x,q2.x)<min(p1.x,p2.x)||max((max(p1.y,p2.y)<min(q1.y,q2.y)||max(q1.y,q2.y)<min(p1.y,p2.y))return
0; if(mul(q1,p1,p2)*mul(p2,p1,q2)<=0&&mul(p1,q2,q1)*mul(q1,q2,p2)<=0)return 1; return 0; } int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } void uone(int a,b){ int t1=find(a),t2=find(b); if(t1==t2)return; if(rk[t1]>rk[t2])fa[t2]=t1; else fa[t1]=t2; if(rk[t1]==rk[t2])rk[t2]++; } For(i,2,n) For(j,1,i-1) if(find(i)!=find(j)&&insect(seg[i].a,seg[i].b,seg[j].a,seg[j].b)) uone(i,j);

POJ1127 Jack Straws