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

    从左边不能到达右边当且仅当存在一条与上下底边相连的分割线将它们分开

    设下底边为S,上底边为T,每个元件作为点,有公共部分的两个点互相连边

    最后拆点求最小割

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N=620,inf=~0U>>2;
    int n,i,j,x,y,S,T,h[N],gap[N],ans;
    struct P{int x1,y1,x2,y2,r,t,x,y;}a[N];
    struct edge{int t,f;edge *nxt,*pair;}*g[N],*d[N];
    inline void add(int s,int t,int f){
      edge *p=new(edge);p->t=t;p->f=f;p->nxt=g[s];g[s]=p;
      p=new(edge);p->t=s;p->f=0;p->nxt=g[t];g[t]=p;
      g[s]->pair=g[t];g[t]->pair=g[s];
    }
    int sap(int v,int flow){
      if(v==T)return flow;
      int rec=0;
      for(edge*p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){
        int ret=sap(p->t,std::min(flow-rec,p->f));
        p->f-=ret;p->pair->f+=ret;d[v]=p;
        if((rec+=ret)==flow)return flow;
      }
      d[v]=g[v];
      if(!(--gap[h[v]]))h[S]=T;
      gap[++h[v]]++;
      return rec;
    }
    inline int sqr(int x){return x*x;}
    inline double dis(int x1,int y1,int x2,int y2){return sqrt(sqr(x1-x2)+sqr(y1-y2))-1e-8;}
    inline bool check(P a,P b){
      if(a.t==1&&b.t==1)return dis(a.x,a.y,b.x,b.y)<=1.0*a.r+b.r;
      if(a.t==2&&b.t==1){P c=a;a=b;b=c;}
      if(a.t==1&&b.t==2){
        if(dis(a.x,a.y,b.x1,b.y1)<=a.r)return 1;
        if(dis(a.x,a.y,b.x1,b.y2)<=a.r)return 1;
        if(dis(a.x,a.y,b.x2,b.y1)<=a.r)return 1;
        if(dis(a.x,a.y,b.x2,b.y2)<=a.r)return 1;
        if(b.x2>a.x&&b.x1<a.x)if(fabs(b.y2-a.y)<=a.r||fabs(b.y1-a.y)<=a.r)return 1;
        if(b.y2>a.y&&b.y1<a.y)if(fabs(b.x2-a.x)<=a.r||fabs(b.x1-a.x)<=a.r)return 1;
        return b.x1<=a.x&&a.x<=b.x2&&b.y1<=a.y&&a.y<=b.y2;
      }
      return !(b.x2<a.x1||b.x1>a.x2||b.y2<a.y1||b.y1>a.y2);
    }
    int main(){
      scanf("%d%d%d",&x,&y,&n);S=n*2+1,T=S+1;
      for(i=1;i<=n;i++)add(i,i+n,1),add(i+n,i,1);
      a[0].t=2,a[0].y1=-1,a[0].x2=x;
      a[n+1].t=2,a[n+1].y1=y,a[n+1].x2=x,a[n+1].y2=y+1;
      for(i=1;i<=n;i++){
        scanf("%d",&a[i].t);
        if(a[i].t==1)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].r);else scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
        for(j=1;j<i;j++)if(check(a[i],a[j]))add(i+n,j,inf),add(j+n,i,inf);
      }
      for(i=1;i<=n;i++)if(check(a[i],a[0]))add(S,i,inf);
      for(i=1;i<=n;i++)if(check(a[i],a[n+1]))add(i+n,T,inf);
      for(gap[i=0]=T;i<=T;i++)d[i]=g[i];
      while(h[S]<T)ans+=sap(S,inf);
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    算法导论(1)堆排序
    Opencv--HoughCircles源码剖析
    数据结构算法应用C++语言描述——(1)C++基础知识
    Java编程的23种设计模式
    团队建设
    管理方法论和角色认知
    压力测试:怎样设计全链路压力测试平台
    09-数据库优化方案(二):写入数据量增加时,如何实现分库分表
    08-数据库优化方案(一):查询请求增加时,如何做主从分离
    07-池化技术:如何减少频繁创建数据库连接的性能损耗
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403191.html
Copyright © 2011-2022 走看看