zoukankan      html  css  js  c++  java
  • [bzoj4823][Cqoi2017]老C的方块

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    挺有意思的一道题....

    看完题面比较明确是最小割,考虑怎么建图 想了比较久 

    突破口应该是题目中那张奇怪的图

    观察这个奇怪的图和方块,很容易发现每个图案,其实都是每个分割线周围各一个1*2的块拼在一起的

    假如中间有个分割线,那么就是这样,两边分别三选一

    然后可以依此根据块的位置不同建出图,我大概画了一部分,大家可以参考

    这张图中行从下到上,列从左到右

    然后注意把点拆成入点和出点,中间连费用的边 最小割即可。

    可以哈希来查点

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<cstring>
    #define S 0
    #define MN 100000
    #define INF 2000000000
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    map<ll,int> mp;
    struct edge{int to,next,w;}e[5000000];
    int n,m,c,T,head[MN*2+5],C[MN*2+5],q[MN*2+5],top=0,d[MN*2+5],cnt=1,ans=0;
    struct Block{int x,y,w;}b[MN+5];
    inline void ins(int f,int t,int w)
    {
        if(!t) return;
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;    
    }
    inline int num(int x,int y)
    {
        if(x>n||y>m||x<1||y<1) return 0;
        int res=mp[1LL*x*MN+y];
        return res?res+c:0;    
    }
    
    int dfs(int x,int f)
    {
        if(x==T) return f;
        int used=0;
        for(int&i=C[x];i;i=e[i].next)
            if(e[i].w&&d[e[i].to]==d[x]+1)
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(used==f) return f;
            }
        return d[x]=-1,used;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(int)*(T+1));int i,j;
        for(d[q[top=i=1]=S]=1;i<=top;++i)
            for(int j=C[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T];
    }
    
    int main()
    {
        m=read();n=read();c=read();T=c*2+1;
        for(int i=1;i<=c;++i) b[i].y=read(),b[i].x=read(),b[i].w=read(),mp[1LL*b[i].x*MN+b[i].y]=i;
        for(int i=1;i<=c;++i)
        {
            ins(i+c,i,b[i].w);
            if(b[i].x&1)
            {
                int cas=b[i].y%4;
                if(cas==0)
                {
                    ins(S,i+c,INF);
                    ins(i,num(b[i].x+1,b[i].y),INF);
                    ins(i,num(b[i].x-1,b[i].y),INF);
                    ins(i,num(b[i].x,b[i].y+1),INF);    
                }
                if(cas==1) ins(i,num(b[i].x,b[i].y+1),INF);
                if(cas==2) 
                {
                    ins(i,num(b[i].x+1,b[i].y),INF);
                    ins(i,num(b[i].x-1,b[i].y),INF);
                    ins(i,num(b[i].x,b[i].y+1),INF);
                }
                if(cas==3) ins(i,T,INF);
            }
            else
            {
                int cas=b[i].y%4;
                if(cas==0) ins(i,num(b[i].x,b[i].y-1),INF);
                if(cas==1) 
                { 
                    ins(S,i+c,INF);
                    ins(i,num(b[i].x,b[i].y-1),INF);
                    ins(i,num(b[i].x+1,b[i].y),INF);    
                    ins(i,num(b[i].x-1,b[i].y),INF);
                } 
                if(cas==2) ins(i,T,INF);
                if(cas==3) 
                {
                    ins(i,num(b[i].x,b[i].y-1),INF);
                    ins(i,num(b[i].x-1,b[i].y),INF);
                    ins(i,num(b[i].x+1,b[i].y),INF);    
                }
            }
        }
        while(bfs()) ans+=dfs(S,INF);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    面向对象设计的原则里氏代换原则
    阅读源码的一些错误观念
    gdb的一个bug Internal error: 【pc 0xxxxxxx】 in read in psymtab, but not in symtab
    STL中mem_fun和mem_fun_ref的用法
    每天写出好代码的5个建议
    /dev/null /dev/zero/
    SQL Server 2008 对 TSQL 语言的增强
    JQuery 应用JQuery.groupTable.js(二)
    jquery 实现iframe 自适应高度
    JQuery 应用JQuery.groupTable.js
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4823.html
Copyright © 2011-2022 走看看