zoukankan      html  css  js  c++  java
  • E. Bricks(最少1*x 覆盖矩阵,最大独立集)

    题:https://codeforces.com/contest/1404/problem/E

    题意:给定n*m矩阵‘#’表示要用砖头覆盖,‘.’表示不能被覆盖,只有1*x的砖头(x可任意),问在砖头不相互覆盖的前提下,最少用几块砖头能按规定把矩阵覆盖

    分析:

    • 假设一开始全部都是1*1的砖头去覆盖,那么就有sum块(‘#’点的个数),要是相邻边合并sum减1,那么就是求在合法情况下最多能合并多少边;
    • 在合法情况下就是限制的1*x,也就不能出现‘L’型砖头,假设要是俩块砖头能形成‘L’型,那么就将这俩块砖头连边(以对偶图的形式)(这明显就是一个二分图的模型);
    • 合法情况就是求独立集(点集中各点没有连边)大小;
    • 而最大独立集就是二分图中节点-最小点覆盖,应用到这道题上就是去掉这些点,相应连的边也就没有了,相当于花了贡献把这些点独立出来,剩下的点也就相互独立了;
    • ans=sum-最大独立集。
    • (下图标号只是方便,不代表该点的真实点标号)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define pb push_back
    const int inf=0x3f3f3f3f;
    const ll INF=(1ll<<40);
    const int M=1e6+5;
    const int N=250;
    int tot,S,T,n,m;
    struct node{
        int u,v,nextt;
        int w;
    }e[M<<1];
    char s[N][N];
    int head[M],deep[M],cur[M];
    void addedge(int u,int v,int w){
        e[tot].v=v;
        e[tot].w=w;
        e[tot].nextt=head[u];
        head[u]=tot++;
        e[tot].v=u;
        e[tot].w=0;
        e[tot].nextt=head[v];
        head[v]=tot++;
    }
    bool bfs(){
        for(int i=0;i<=T;i++)
            deep[i]=0;
        queue<int>que;
        que.push(S);
        deep[S]=1;
        while(!que.empty()){
            int u=que.front();
            que.pop();
            for(int i=head[u];~i;i=e[i].nextt){
                int v=e[i].v;
                if(e[i].w>0&&deep[v]==0){
                    deep[v]=deep[u]+1;
                    if(v==T)
                        return true;
                    que.push(v);
                }
            }
        }
        return deep[T]!=0;
    }
    int dfs(int u,int fl){
    
        if(u==T)
            return fl;
        int ans=0,x=0;
        for(int i=cur[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(e[i].w>0&&deep[v]==deep[u]+1){
                x=dfs(v,min(fl-ans,e[i].w));
                e[i].w-=x;
                e[i^1].w+=x;
                ans+=x;
                if(ans==fl)
                    return ans;
                if(e[i].w)
                    cur[u]=i;
    
            }
        }
        if(ans==0)
            deep[u]=0;
        return ans;
    }
    int dinic(){
        int res=0;
        while(bfs()){
            for(int i=0;i<=T;i++)
                cur[i]=head[i];
            res+=dfs(S,inf);
        }
        return res;
    }
    int getid(int x,int y,int other){
        return (x-1)*m+y+other;
    }
    int main(){
    
        scanf("%d%d",&n,&m);
    
        S=2*n*m+10,T=S+1;
        for(int i=0;i<=T;i++)
            head[i]=-1;
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]+1);
    
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                if(s[i][j]=='#'){
                    ///将横纵作为二分图的两边
                    ///L R在对偶图上相差1
                    int L = (j-1>=1&&s[i][j-1]=='#') ? getid(i,j-1,0) : 0;
                    int R = (j+1<=m&&s[i][j+1]=='#') ? getid(i,j-1,1) : 0;
                    ///U D在对偶图上相差m
                    int U = (i-1>=1&&s[i-1][j]=='#') ? getid(i-1,j,n*m) : 0;
                    int D = (i+1<=n&&s[i+1][j]=='#') ? getid(i-1,j,n*m+m) : 0;
                    if(L&&U) addedge(L,U,1);
                    if(L&&D) addedge(L,D,1);
                    if(R&&U) addedge(R,U,1);
                    if(R&&D) addedge(R,D,1);
                }
        }
        int sum=0;
        int res=0;///二分图点数
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(s[i][j]=='#'){
                    sum++;
                    ///row点连接S
                    if(j+1<=m&&s[i][j+1]=='#')
                        addedge(S,getid(i,j-1,1),1),res++;
                    ///colu点连接T
                    if(i+1<=n&&s[i+1][j]=='#')
                        addedge(getid(i-1,j,n*m+m),T,1),res++;
                }
    
        printf("%d
    ",sum-(res-dinic()));
        return 0;
    }
    View Code
  • 相关阅读:
    centos安装elasticsearch-rtf5.5.4
    docker的8个使用场景
    通过优化Gunicorn配置获得更好的性能
    django更换ORM连接处理(连接池)转
    单点登录,系统B如何辨别用户已登录系统A
    数据库Mysql的学习(六)-子查询和多表操作
    数据库Mysql的学习(五)-运算符与函数
    数据库Mysql的学习(四)-表的记录操作
    数据库Mysql的学习(三)-各种约束
    c和c++单链表
  • 原文地址:https://www.cnblogs.com/starve/p/13642151.html
Copyright © 2011-2022 走看看