• 【BZOJ3630】镜面通道(JLOI2014)-最小割+计算几何


    测试地址:镜面通道
    做法:本题需要用到最小割+计算几何。
    首先根据一个神奇的物理学定理:水能通过的地方,光就能通过,所以我们要求的就是AB和CD所属的平面区域连通,继而就是求上边界和下边界不能通过元件连通。因此我们在连通的两个元件之间连边,要求至少要去掉多少个点使得两个点不连通,我们发现这就是一个最小割,然而是对于点的最小割。对此我们把一个点拆成两个点,分为入点和出点,并将所有涉及该点的入边连向入点,将所有涉及该点的出边从出点连出,然后从入点向出点连一条容量为1的边。那么割点就变成了割边,原图中所有其他的边容量都设成正无穷的话,最小割中一定不包含原图中的边,那么直接求最小割即可。
    这题还有一个难点就是判断两个元件相交/相切,这里讲讲我的做法:
    对于矩形和矩形,因为它们都平行于坐标轴,所以我们把它们都投影到两条坐标轴上,并看看它们在坐标轴上的投影是不是都相交,如果都相交的话这两个矩形就是相交的。
    对于圆和圆,如果它们圆心间的距离小于等于它们半径的和,那它们就是相交的。
    对于矩形和圆,因为本题中互相包含我们也算作相交,所以先判断圆心是不是在矩形内,如果在的话显然相交,否则算出圆心和矩形四边间的最小距离,如果这个最小距离小于等于半径,那么也说明它们相交。
    这样我们就做完了这一题。
    我傻逼的地方:犯了史上最傻逼的错误之一——数组开小。但是BZOJ和洛谷纷纷显示WA而不是RE,所以我就没仔细看,很是诡异……这种水题都调了我半天啊……
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=1000000000;
    ll x,y;
    int n,S,T,first[610]={0},tot=1;
    int h,t,q[610],lvl[610];
    struct shape
    {
        int type;
        ll x1,y1,x2,y2,r;
    }a[310];
    struct edge
    {
        int v,next,f;
    }e[500010];
    
    void insert(int a,int b,int f)
    {
        e[++tot].v=b;e[tot].next=first[a];e[tot].f=f;first[a]=tot;
        e[++tot].v=a;e[tot].next=first[b];e[tot].f=0;first[b]=tot;
    }
    
    bool Judge(int x,int y)
    {
        if (a[x].x1>a[y].x1) swap(x,y);
        if (a[x].x2<a[y].x1) return 0;
        if (a[x].y1>a[y].y1) swap(x,y);
        if (a[x].y2<a[y].y1) return 0;
        return 1;
    }
    
    ll dis(ll x1,ll y1,ll x2,ll y2)
    {
        return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
    }
    
    ll calc(ll x,ll y,ll t1,ll t2,ll t3,bool type)
    {
        if (!type)
        {
            if (x<=t1) return dis(x,y,t1,t3);
            if (x>=t2) return dis(x,y,t2,t3);
            return (y-t3)*(y-t3);
        }
        else
        {
            if (y<=t1) return dis(x,y,t3,t1);
            if (y>=t2) return dis(x,y,t3,t2);
            return (x-t3)*(x-t3);
        }
    }
    
    bool check(int x,int y)
    {
        if (a[x].type!=2) swap(x,y);
        if (a[x].type==2)
        {
            if (a[y].type==2) return Judge(x,y);
            else
            {
                if (a[y].x1>=a[x].x1&&a[y].x1<=a[x].x2&&a[y].y1>=a[x].y1&&a[y].y1<=a[y].y2) return 1;
                if (calc(a[y].x1,a[y].y1,a[x].x1,a[x].x2,a[x].y1,0)<=a[y].r*a[y].r) return 1;
                if (calc(a[y].x1,a[y].y1,a[x].x1,a[x].x2,a[x].y2,0)<=a[y].r*a[y].r) return 1;
                if (calc(a[y].x1,a[y].y1,a[x].y1,a[x].y2,a[x].x1,1)<=a[y].r*a[y].r) return 1;
                if (calc(a[y].x1,a[y].y1,a[x].y1,a[x].y2,a[x].x2,1)<=a[y].r*a[y].r) return 1;
                return 0;
            }
        }
        else return dis(a[x].x1,a[x].y1,a[y].x1,a[y].y1)<=(a[x].r+a[y].r)*(a[x].r+a[y].r);
    }
    
    void init()
    {
        scanf("%lld%lld",&x,&y);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].type);
            if (a[i].type==1) scanf("%lld%lld%lld",&a[i].x1,&a[i].y1,&a[i].r);
            else scanf("%lld%lld%lld%lld",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
        }
        a[0].type=2,a[0].x1=0,a[0].x2=x,a[0].y1=a[0].y2=y;
        a[n+1].type=2,a[n+1].x1=0,a[n+1].x2=x,a[n+1].y1=a[n+1].y2=0;
    
        S=(n<<1)+1,T=(n<<1)+2;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if (check(i,j)) insert(n+i,j,inf),insert(n+j,i,inf);
        for(int i=1;i<=n;i++)
        {
            insert(i,n+i,1);
            if (check(0,i)) insert(S,i,inf);
            if (check(n+1,i)) insert(n+i,T,inf); 
        }
    }
    
    bool makelevel()
    {
        for(int i=1;i<=T;i++)
            lvl[i]=-1;
        h=t=1;
        q[1]=S;
        lvl[S]=0;
        while(h<=t)
        {
            int v=q[h++];
            for(int i=first[v];i;i=e[i].next)
                if (e[i].f&&lvl[e[i].v]==-1)
                {
                    lvl[e[i].v]=lvl[v]+1;
                    q[++t]=e[i].v;
                }
        }
        return lvl[T]!=-1;
    }
    
    int maxflow(int v,int maxf)
    {
        int ret=0,f;
        if (v==T) return maxf;
        for(int i=first[v];i;i=e[i].next)
            if (e[i].f&&lvl[e[i].v]==lvl[v]+1)
            {
                f=maxflow(e[i].v,min(maxf-ret,e[i].f));
                ret+=f;
                e[i].f-=f;
                e[i^1].f+=f;
                if (ret==maxf) return ret;
            }
        return ret;
    }
    
    void dinic()
    {
        int maxf=0;
        while(makelevel())
            maxf+=maxflow(S,inf);
        printf("%d",maxf);
    }
    
    int main()
    {
        init();
        dinic();
    
        return 0;
    }
  • 相关阅读:
    K8S-安全机制
    K8S-Service
    K8S-Pod资源管理
    K8S-kubelet启动过程
    每日进度
    每日进度
    每日进度
    每日进度
    每日进度
    归纳及计划
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793448.html
Copyright © 2020-2023  润新知