POJ 3336 ACM Underground(计算几何预处理并查集)
下面附上至今为止全网第一篇poj3336含代码的博客。
题目链接:https://vjudge.net/problem/POJ-3336
emm这题vjudge上只有五个人过。。。而且搜了一搜好像并没有看到题解,所以来写一写题解吧。
题意:给你n条线段,m个点,问你能不能从起点沿着线段到达终点,线段之间可以切换。限制 :1、点不在线段之间的交点上,不可以经过该点。2、点在线段之间的交点上,可以经过该点,但是不能在该点上切换线段。n 3000,m100.
我们可以把m个点分出来的线段处理出来(线段相交先不算)。然后可以预计处理出来的线段是不会达到上界(nm)的,(我也不知道为什么,反正可以暴力做就对了)。然后我们可以枚举两个线段,判断他们是否相交,如果相交并且交点不是所给的m个点,那么就并查集合并为一个集合。然后最后看看起点和终点所在的线段是不是一个集合就好了,这题也没什么坑。
附上代码:
1 /************************************************************************* 2 > File Name: poj3336.cpp 3 # File Name: poj3336.cpp 4 # Author : xiaobuxie 5 # QQ : 760427180 6 # Email:760427180@qq.com 7 # Created Time: 2019年10月25日 星期五 21时30分26秒 8 ************************************************************************/ 9 10 #include<iostream> 11 #include<cstdio> 12 #include<map> 13 #include<cmath> 14 #include<cstring> 15 #include<set> 16 #include<queue> 17 #include<vector> 18 #include<algorithm> 19 using namespace std; 20 typedef long long ll; 21 #define inf 0x3f3f3f3f 22 #define eps 1e-8 23 int sgn(double x){ 24 if(fabs(x) < eps) return 0; 25 if(x<0) return -1; 26 return 1; 27 } 28 const int N = 2e6; 29 const int M = 400; 30 int f[N]; 31 struct Point{ 32 double x,y; 33 Point(){x=y=0;} 34 Point(double a,double b){x=a,y=b;} 35 Point operator - (const Point& b)const 36 {return Point(x-b.x,y-b.y);} 37 Point operator + (const Point& b)const 38 {return Point(x+b.x,y+b.y);} 39 Point operator * (const double& b)const 40 {return Point(x*b,y*b);} 41 double operator ^ (const Point& b)const 42 {return x*b.y - b.x * y;} 43 double dot (const Point& b)const 44 {return x*b.x+y*b.y;} 45 double cross (const Point& b,const Point& c)const 46 {return (b.x - x)*(c.y - y) - (c.x - x)*(b.y - y);} 47 double dis (const Point& b)const 48 {return sqrt( (x-b.x)*(x-b.x) + (y-b.y)*(y-b.y) );} 49 bool OnLine (const Point& st,Point& ed)const 50 {return !sgn(cross(st,ed));} 51 bool OnSeg (const Point& st,Point& ed)const 52 {return OnLine(st,ed) && (*this - ed).dot(*this - st) < eps;} 53 bool operator < (const Point& b)const{ 54 if(x == b.x ) return y<b.y; 55 return x<b.x; 56 } 57 bool operator != (const Point& b)const{ 58 return x!=b.x || y!=b.y; 59 } 60 }p[M]; 61 Point st,ed; 62 struct Segment{ 63 Point s,t; 64 }L[N]; 65 int n,m; 66 map< Point , int > mp; 67 int find(int x){ 68 if(x == f[x]) return x; 69 return f[x] = find(f[x]); 70 } 71 bool inter(Segment a,Segment b){ 72 if( sgn(a.s.cross(b.s,b.t)) * sgn(a.t.cross(b.s,b.t)) > 0) return 0; 73 if( sgn(b.s.cross(a.s,a.t)) * sgn(b.t.cross(a.s,a.t)) > 0) return 0; 74 return 1; 75 } 76 Point inter_point(Segment l1,Segment l2){ 77 double b = ( (l1.t - l1.s) ^ (l2.s - l1.s) ) / ( (l2.t - l2.s)^(l1.t - l1.s)); 78 return l2.s + (l2.t - l2.s)*b; 79 } 80 int main(){ 81 int T; scanf("%d",&T); 82 while(T--){ 83 mp.clear(); 84 scanf("%d %d",&n,&m); 85 scanf("%lf %lf %lf %lf",&st.x,&st.y,&ed.x,&ed.y); 86 for(int i = 1;i<=n;++i) scanf("%lf %lf %lf %lf",&L[i].s.x,&L[i].s.y,&L[i].t.x,&L[i].t.y); 87 for(int i = 1;i<=m;++i) scanf("%lf %lf",&p[i].x,&p[i].y); 88 int cnt = n; 89 for(int i = 1;i<=n;++i){ 90 for(int j = i+1;j<=n;++j){ 91 Point tp = inter_point(L[i],L[j]); 92 if( (!tp.OnSeg(L[i].s,L[i].t)) || (!tp.OnSeg(L[j].s,L[j].t)) ) continue; 93 // cerr<<i<<' '<<j<<' '<<tp.x<<' '<<tp.y<<endl; 94 mp[tp] = 1; 95 } 96 } 97 for(int i = 1;i<=m;++i){ 98 for(int j = 1;j<=cnt;++j){ 99 if(mp[p[i]]){ 100 mp[ p[i] ] = 2; 101 continue; 102 } 103 // cerr<<i<<'a'<<endl; 104 if(p[i].OnSeg(L[j].s,L[j].t) && p[i]!=L[j].s && p[i]!=L[j].t ){ 105 L[++cnt] = L[j]; 106 L[j].t = p[i]; 107 L[cnt].s = p[i]; 108 mp[ p[i] ] = 3; 109 } 110 } 111 } 112 for(int i = 1; i<=cnt;++i) f[i] = i; 113 for(int i = 1;i<=cnt;++i){ 114 for(int j = i + 1;j<=cnt;++j){ 115 Point tp = inter_point(L[i],L[j]); 116 // cerr<<i<<' '<<j<<' '<<tp.x<<' '<<tp.y<<'p'<<endl; 117 if( !tp.OnSeg(L[i].s,L[i].t) ) continue; 118 // cerr<<'a'<<endl; 119 if( !tp.OnSeg(L[j].s,L[j].t) ) continue; 120 // cerr<<'b'<<endl; 121 if(mp[tp] == 2) continue; 122 // cerr<<'c'<<endl; 123 int fi = find(i); 124 int fj = find(j); 125 f[fj] = fi; 126 // cerr<<i<<' '<<j<<"BIN"<<endl; 127 } 128 } 129 130 // for(int i = 1;i<=cnt;++i) cerr<<i<<' '<<f[i]<<' '<<L[i].s.x<<' '<<L[i].s.y<<' '<<L[i].t.x<<' '<<L[i].t.y<<endl; 131 int ids,idt; 132 for(int i = 1;i<=cnt;++i){ 133 if( st.OnSeg(L[i].s,L[i].t) ){ 134 ids = i; 135 break; 136 } 137 } 138 for(int i = 1;i<=cnt;++i){ 139 if(ed.OnSeg(L[i].s,L[i].t)){ 140 idt = i; 141 break; 142 } 143 } 144 // cerr<<'b'<<ids<<' '<<idt<<endl; 145 int fs = find(ids); 146 int ft = find(idt); 147 if(fs == ft) puts("YES"); 148 else puts("NO"); 149 } 150 return 0; 151 }