zoukankan      html  css  js  c++  java
  • BZOJ3630: [JLOI2014]镜面通道

    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
    ",dinic());
    }
    
  • 相关阅读:
    2020年,初级、中级 Android 工程师可能因离职而失业吗?
    Android 后台运行白名单,优雅实现保活
    使用DataBinding还在为数据处理头疼?这篇文章帮你解决问题
    Android 7.x Toast BadTokenException处理
    2017-2020历年字节跳动Android面试真题解析(累计下载1082万次,持续更新中)
    Flutter 尺寸限制类容器总结:这可能是全网解析最全的一篇文章,没有之一!
    并行收集器
    高性能索引策略
    Innodb简介
    索引的优点
  • 原文地址:https://www.cnblogs.com/suika/p/10205539.html
Copyright © 2011-2022 走看看