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:[email protected]
  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 }
View Code

猜你喜欢

转载自www.cnblogs.com/xiaobuxie/p/11743391.html
今日推荐