BZOJ3630: [JLOI2014]鏡面通道
阿新 • • 發佈:2019-01-01
dot bfs code algorithm per ring %d inline math
BZOJ3630: [JLOI2014]鏡面通道
https://lydsy.com/JudgeOnline/problem.php?id=3630
分析:
- 拆點,相交則連邊\(inf\),求最小割既是答案。
- 圓圓交 : 求圓點距離即可
- 矩矩交 : 考慮補集,就是不相交的情況,一定有四種大小關系發生(如代碼)
- 圓矩交 : 很坑,先判直接相交,即圓心到邊的距離小於等於半徑。
- 再判矩形包含圓,即圓心在矩形內部。
代碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <vector> #include <iostream> #include <cmath> using namespace std; #define N 650 #define M 1000050 #define inf 0x3f3f3f3f int is[N][N]; typedef double f2; const int S=648,T=649; int head[N],to[M],nxt[M],flow[M],cnt=1,n; int U,dep[N],Q[N]; inline void add(int u,int v,int f) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f; to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0; } bool bfs() { int l=0,r=0; memset(dep,0,sizeof(dep)); Q[r++]=S; dep[S]=1; while(l<r) { int x=Q[l++],i; for(i=head[x];i;i=nxt[i]) if(!dep[to[i]]&&flow[i]) { dep[to[i]]=dep[x]+1; if(to[i]==T) return 1; Q[r++]=to[i]; } } return 0; } int dfs(int x,int mf) { if(x==T) return mf; int i,nf=0; for(i=head[x];i;i=nxt[i]) if(dep[to[i]]==dep[x]+1&&flow[i]) { int tmp=dfs(to[i],min(mf-nf,flow[i])); if(!tmp) dep[to[i]]=0; nf+=tmp; flow[i]-=tmp; flow[i^1]+=tmp; if(nf==mf) break; }return nf; } int dinic() { int maxf=0,f; while(bfs()) { while((f=dfs(S,inf))) maxf+=f; } return maxf; } struct Point { int x,y; Point() {} Point(int x_,int y_) {x=x_,y=y_;} Point operator - (const Point &p) const {return Point(x-p.x,y-p.y);} }; f2 pf(f2 x) {return x*x;} f2 dot(const Point &p1,const Point &p2) {return 1.0*p1.x*p2.x+1.0*p1.y*p2.y;} f2 cross(const Point &p1,const Point &p2) {return 1.0*p1.x*p2.y-1.0*p1.y*p2.x;} f2 dis(const Point &p1,const Point &p2) {return sqrt(pf(p1.x-p2.x)+pf(p1.y-p2.y));} Point pt[N]; int rr[N],c1,c2,id1[N],id2[N]; int xx1[N],xx2[N],yy1[N],yy2[N]; struct Line { Point p1,p2; }; f2 dpl(const Point &p1,const Point &p2,const Point &p3) { if(dot(p3-p1,p3-p2)<0||dot(p2-p1,p2-p3)<0) return min(dis(p1,p2),dis(p1,p3)); return abs(cross(p2-p1,p3-p1)/dis(p2,p3)); } int main() { int X; scanf("%d%d%d",&X,&U,&n); int i,opt,j; for(i=1;i<=n;i++) { scanf("%d",&opt); if(opt==1) { ++c1; id1[c1]=i; scanf("%d%d%d",&pt[c1].x,&pt[c1].y,&rr[c1]); }else { c2++; id2[c2]=i; scanf("%d%d%d%d",&xx1[c2],&yy1[c2],&xx2[c2],&yy2[c2]); } } for(i=1;i<=c1;i++) if(pt[i].x>=0&&pt[i].x<=X) { if(pt[i].y<=rr[i]) add(id1[i]+n,T,inf); if(U-pt[i].y<=rr[i]) add(S,id1[i],inf); } for(i=1;i<=c2;i++) if(xx1[i]>=0&&xx2[i]<=X) { if(yy1[i]<=0) add(id2[i]+n,T,inf); if(yy2[i]>=U) add(S,id2[i],inf); } for(i=1;i<=n;i++) add(i,i+n,1); for(i=1;i<=c1;i++) { for(j=i+1;j<=c1;j++) { if(dis(pt[i],pt[j])<=rr[i]+rr[j]) add(id1[i]+n,id1[j],inf),add(id1[j]+n,id1[i],inf),is[id1[i]][id1[j]]=is[id1[j]][id1[i]]=1; } } for(i=1;i<=c2;i++) { for(j=i+1;j<=c2;j++) { if(xx1[i]>xx2[j]||xx1[j]>xx2[i]||yy1[i]>yy2[j]||yy1[j]>yy2[i]) continue; add(id2[i]+n,id2[j],inf); add(id2[j]+n,id2[i],inf); is[id2[i]][id2[j]]=is[id2[j]][id2[j]]=1; } } for(i=1;i<=c1;i++) { for(j=1;j<=c2;j++) { Point p1=Point(xx1[j],yy1[j]),p2=Point(xx1[j],yy2[j]),p3=Point(xx2[j],yy1[j]),p4=Point(xx2[j],yy2[j]); if(dpl(pt[i],p1,p2)<=rr[i]||dpl(pt[i],p2,p4)<=rr[i]||dpl(pt[i],p3,p4)<=rr[i]||dpl(pt[i],p1,p3)<=rr[i]) { add(id1[i]+n,id2[j],inf); add(id2[j]+n,id1[i],inf); is[id1[i]][id2[j]]=is[id2[j]][id1[i]]=1; }else if(pt[i].x>=xx1[j]&&pt[i].x<=xx2[j]&&pt[i].y>=yy1[j]&&pt[i].y<=yy2[j]) { add(id1[i]+n,id2[j],inf); add(id2[j]+n,id1[i],inf); is[id1[i]][id2[j]]=is[id2[j]][id1[i]]=1; } } } printf("%d\n",dinic()); }
BZOJ3630: [JLOI2014]鏡面通道