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

      如果将其转化为一个更一般的问题即二分图带权最小单边点覆盖(最小控制集)感觉是非常npc的。考虑原题给的一大堆东西究竟有什么奇怪的性质。

      容易发现如果与特殊边相邻的两格子都放了方块,并且这两个格子都各有另一个相邻格子放了方块,其组成的连通块就是需要破坏的。自然四个格子都可以选择破坏。可以发现如果在中间的两个格子里选的话,应该选择破坏权值较小的,因为其对其他格子没有影响。同时注意到另两个格子在黑白染色的图中一定是不同色的。

      那么做法就很显然了,建四层点,外部两层是不与特殊边相邻的黑白点,内部两层是与特殊边相邻的黑白点,外部点分别与源汇连边权为其权值的边,内部点之间连边权为较小权值的边,外部点和内部点之间连inf边,跑最小割即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    #define ll long long
    #define N 100010
    #define S 0
    #define T 100001
    #define inf 1000000010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int c,r,n,p[N],t=-1;
    int d[N],cur[N],q[N],ans;
    struct data{int to,nxt,cap,flow;
    }edge[N<<5];
    struct data2{int x,y;
    }a[N];
    map<int,int> f[N],id[N];
    int wx[4]={1,0,0,-1},wy[4]={0,1,-1,0};
    void addedge(int x,int y,int z)
    {
        t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=0,p[x]=t;
        t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,p[y]=t;
    }
    bool isblack(int x,int y){return x+y&1;}
    bool isnear(int x,int y){return x&1?y%4==1||y%4==2:y%4==0||y%4==3;}
    bool bfs()
    {
        memset(d,255,sizeof(d));d[S]=0;
        int head=0,tail=1;q[1]=S;
        do
        {
            int x=q[++head];
            for (int i=p[x];~i;i=edge[i].nxt)
            if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap)
            {
                d[edge[i].to]=d[x]+1;
                q[++tail]=edge[i].to;
            }
        }while (head<tail);
        return ~d[T];
    }
    int work(int k,int f)
    {
        if (k==T) return f;
        int used=0;
        for (int i=cur[k];~i;i=edge[i].nxt)
        if (d[k]+1==d[edge[i].to])
        {
            int w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow));
            edge[i].flow+=w,edge[i^1].flow-=w;
            if (edge[i].flow<edge[i].cap) cur[k]=i;
            used+=w;if (used==f) return f;
        }
        if (used==0) d[k]=-1;
        return used;
    }
    void dinic()
    {
        while (bfs())
        {
            memcpy(cur,p,sizeof(p));
            ans+=work(S,inf);
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4823.in","r",stdin);
        freopen("bzoj4823.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        c=read(),r=read(),n=read();
        memset(p,255,sizeof(p));
        for (int i=1;i<=n;i++)
        {
            int y=read(),x=read(),z=read();
            f[a[i].x=x][a[i].y=y]=z;id[x][y]=i;
        }
        for (int i=1;i<=n;i++)
        if (!isnear(a[i].x,a[i].y)&&isblack(a[i].x,a[i].y))
        {
            addedge(S,i,f[a[i].x][a[i].y]);
            for (int j=0;j<4;j++)
            if (isnear(a[i].x+wx[j],a[i].y+wy[j])&&id[a[i].x+wx[j]][a[i].y+wy[j]])
                for (int k=0;k<4;k++)
                if (isnear(a[i].x+wx[j]+wx[k],a[i].y+wy[j]+wy[k])&&id[a[i].x+wx[j]+wx[k]][a[i].y+wy[j]+wy[k]])
                    for (int x=0;x<4;x++)
                    {
                        int u=a[i].x+wx[j]+wx[k]+wx[x],v=a[i].y+wy[j]+wy[k]+wy[x];
                        if (!isnear(u,v)&&id[u][v]) addedge(i,id[a[i].x+wx[j]][a[i].y+wy[j]],inf),addedge(id[a[i].x+wx[j]+wx[k]][a[i].y+wy[j]+wy[k]],id[u][v],inf);
                    }
        }
        for (int i=1;i<=n;i++)
        if (!isnear(a[i].x,a[i].y)&&!isblack(a[i].x,a[i].y)) addedge(i,T,f[a[i].x][a[i].y]);
        for (int i=1;i<=n;i++)
        if (isnear(a[i].x,a[i].y)&&!isblack(a[i].x,a[i].y))
            for (int j=0;j<4;j++)
            if (isnear(a[i].x+wx[j],a[i].y+wy[j])&&id[a[i].x+wx[j]][a[i].y+wy[j]])
            addedge(i,id[a[i].x+wx[j]][a[i].y+wy[j]],min(f[a[i].x][a[i].y],f[a[i].x+wx[j]][a[i].y+wy[j]]));
        dinic();
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    python基础(三)python数据类型
    python基础(二)条件判断、循环、格式化输出
    postman测试上传文件
    postman添加权限验证
    postman添加cookie
    postman发送json格式的post请求
    postman发送post请求
    如果json中的key需要首字母大写怎么解决?
    fastjson转jackson
    git初识
  • 原文地址:https://www.cnblogs.com/Gloid/p/9998763.html
Copyright © 2011-2022 走看看