POJ1127 Jack Straws
阿新 • • 發佈:2018-08-04
alt bool span img lse div -a height turn 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)
給你一些線段,求出哪些線段是相連的,哪些是不相連的。相連包括間接相連,即這兩條線段本身不直接相連,而是通過其它線段的連接而間接相連。
線段相交+並查集
這裏主要說如何判斷線段相交:快速排斥試驗+跨立試驗
牢記一點:研究對象一定是兩條線段的四個端點
(快速排斥試驗:只是可以證明這兩條一定不相交,達到一點加速效果)
以線段P1,P2為對角線作一矩形R,再以Q1,Q2為對角線作矩形T,當兩個矩形不相交的時候兩條線段肯定不相交,即線段相交的必要條件時矩形相交。
矩陣相交依據:兩條線段一共四個端點,x/y軸中,最小的兩個端點不能屬於同一條線段
min(p1.x,p2.x)<=max(q1.x,q2.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))return0; 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