zoukankan      html  css  js  c++  java
  • 【BZOJ4823】老C的方块(CQOI2017)-最小割

    测试地址:老C的方块
    做法:本题需要用到最小割。
    看到网格,首先想到黑白染色处理。但是染色之后我们一时还看不出有什么性质,所以我们先分析题目中的条件。
    我们考虑这样一个区域:中间是特殊公共边,包含特殊公共边旁的两个格子和它们相邻的格子,共包含8个格子的区域(想象不出来可以在草稿纸上画画)。我们把中间两个格子称为中间格,其他格子称为边缘格,并称一个边缘格属于一个中间格当且仅当它们相邻。我们发现,题目中的“讨厌的形状”的限制实际上等价于,两个属于不同中间格的边缘格不能连通。要做到这一点,我们有三种选择:
    1.去掉所有属于第一个中间格的边缘格。
    2.去掉所有属于第二个中间格的边缘格。
    3.去掉一个中间格。
    这时我们想到了黑白染色,我们发现属于相同中间格的边缘格颜色相同,反之颜色不同。那么我们可以这样建图:
    1.从黑色的边缘格向它们属于的中间格连边,容量为无穷大。
    2.从白色的边缘格属于的中间格向它们连边,容量为无穷大。
    3.从白色的中间格向黑色的中间格连边,容量为删去它们中一个的最小费用。
    4.从源点向黑色的边缘格连边,容量为删去该边缘格的费用。
    5.从白色的边缘格向汇点连边,容量为删去该边缘格的费用。
    这时我们知道,要使从源点到不了汇点,必须删掉步骤3,4,5中某一个步骤建出的边,而每个步骤唯一对应了上面的一种决策,所以每一个割都对应一种合法的删格子方案,那么问题转化为求最小割,就可以很轻易地完成这题了。别看这题数据范围那么大,实际上Dinic在这种长得像二分图的图中跑得还是很快的,不用担心。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int inf=1000000001;
    int C,R,n,S,T;
    int first[100010]={0},tot=1;
    int h,t,q[100010],cur[100010],lvl[100010];
    struct block
    {
        int id,x,y,w;
    }p[100010];
    struct edge
    {
        int v,next,f;
    }e[2000010];
    
    bool cmpx(block a,block b)
    {
        if (a.x!=b.x) return a.x<b.x;
        else return a.y<b.y;
    }
    
    bool cmpy(block a,block b)
    {
        if (a.y!=b.y) return a.y<b.y;
        else return a.x<b.x;
    }
    
    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;
    }
    
    void init()
    {
        scanf("%d%d%d",&C,&R,&n);
        S=n+1,T=n+2;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].w);
            p[i].id=i;
        }
    
        p[0].x=p[0].y=p[n+1].x=p[n+1].y=0;
        sort(p+1,p+n+1,cmpx);
        for(int i=1;i<=n;i++)
        {
            if (p[i+1].x!=p[i].x||p[i+1].y!=p[i].y+1) continue;
            if ((p[i].x+p[i].y)%2==0) insert(p[i].id,p[i+1].id,inf);
            else insert(p[i+1].id,p[i].id,inf);
        }
    
        sort(p+1,p+n+1,cmpy);
        for(int i=1;i<=n;i++)
        {
            int val;
            if (p[i+1].x!=p[i].x+1||p[i+1].y!=p[i].y) continue;
            if (p[i].x%2&&p[i].y%2==((p[i].x-1)/2)%2) continue;
            if (p[i].x%2) val=min(p[i].w,p[i+1].w);
            else val=inf;
            if (p[i].y%2) insert(p[i+1].id,p[i].id,val);
            else insert(p[i].id,p[i+1].id,val);
        }
    
        for(int i=1;i<=n;i++)
        {
            if (((p[i].x-1)/2)%2==p[i].y%2)
            {
                if ((p[i].x+p[i].y)%2==0) insert(S,p[i].id,p[i].w);
                else insert(p[i].id,T,p[i].w);
            }
        }
    }
    
    bool makelevel()
    {
        for(int i=1;i<=T;i++)
            lvl[i]=-1,cur[i]=first[i];
        lvl[S]=0;
        h=t=1;
        q[1]=S;
        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=cur[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) break;
            }
            cur[v]=i;
        }
        if (!ret) lvl[v]=-1;
        return ret;
    }
    
    void dinic()
    {
        int maxf=0;
        while(makelevel())
            maxf+=maxflow(S,inf);
        printf("%d",maxf);
    }
    
    int main()
    {
        init();
        dinic();
    
        return 0;
    }
  • 相关阅读:
    使用NBU进行oracle异机恢复
    mycat偶尔会出现JVM报错double free or corruption并崩溃退出
    exp导出数据时丢表
    service_names配置不正确,导致dg创建失败
    XML概念定义以及如何定义xml文件编写约束条件java解析xml DTD XML Schema JAXP java xml解析 dom4j 解析 xpath dom sax
    HTTP协议简介详解 HTTP协议发展 原理 请求方法 响应状态码 请求头 请求首部 java模拟浏览器客户端服务端
    java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类
    【JAVA集合框架一 】java集合框架官方介绍 Collections Framework Overview 集合框架总览 翻译 javase8 集合官方文档中文版
    java内部类深入详解 内部类的分类 特点 定义方式 使用
    再谈包访问权限 子类为何不能使用父类protected方法
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793440.html
Copyright © 2011-2022 走看看