zoukankan      html  css  js  c++  java
  • bzoj 2150

    然后考虑正解

    我们发现,最坏情况就是每个点都派驻军队,所以答案至多是“.”的数目

    而且,每个点都至多只有一个入度和一个出度,所以我们可以将每个点拆成两个点,一个作为入点,一个作为出点,然后所有图上能到达的点由出点向入点建图

    这样整个图就形成了一个二分图

    然后在整个图上跑二分图匹配即可

    答案即为“.”点数-二分图最大匹配数

    稍微证明一下:我们的目的是最大化有入边的点的数量,那我们仅需让入点能更多的被匹配上即可

    那也就是二分图匹配喽

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    using namespace std;
    struct Edge
    {
        int next;
        int to;
    }edge[10005];
    int head[2505];
    int maps[55][55];
    char s[55];
    bool used[6005];
    int f[6005];
    int n,m,r,c;
    int cnt=1,cot;
    queue <int> Q;
    bool check(int x,int y)
    {
        if(x>0&&x<=n&&y>0&&y<=m&&maps[x][y])
        {
            return 1;
        }
        return 0;
    }
    void init()
    {
        memset(head,-1,sizeof(head));
        cnt=1;
    }
    void add(int l,int r)
    {
        edge[cnt].next=head[l];
        edge[cnt].to=r;
        head[l]=cnt++;
    }
    int po(int x,int y)
    {
        return (x-1)*m+y; 
    }
    int ppo(int x,int y)
    {
        return (x-1)*m+y+n*m;
    }
    bool dfs(int x)
    {
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            if(used[to])
            {
                continue;
            }
            used[to]=1;
            if(!f[to]||dfs(f[to]))
            {
                f[to]=x;
                return 1;
            }
        }
        return 0;
    }
    int hungary()
    {
        int ret=0;
        while(!Q.empty())
        {
            memset(used,0,sizeof(used));
            int u=Q.front();
            Q.pop();
            if(dfs(u))
            {
                ret++;
            }
        }
        return ret;
    }
    int main()
    {
        freopen("legion.in","r",stdin);
        freopen("legion.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&r,&c);
        init();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
            {
                if(s[j]=='.')
                {
                    maps[i][j]=1;
                    Q.push(po(i,j));
                    cot++;
                }else
                {
                    maps[i][j]=0;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                int x0=i+r;
                int y0=j+c;
                if(check(x0,y0))
                {
                    add(po(i,j),ppo(x0,y0));
                }
                x0=i+r;
                y0=j-c;
                if(check(x0,y0))
                {
                    add(po(i,j),ppo(x0,y0));
                }
                x0=i+c;
                y0=j+r;
                if(check(x0,y0))
                {
                    add(po(i,j),ppo(x0,y0));
                }
                x0=i+c;
                y0=j-r;
                if(check(x0,y0))
                {
                    add(po(i,j),ppo(x0,y0));
                }
            }
        }
        printf("%d
    ",cot-hungary());
        return 0;
    }
  • 相关阅读:
    你本地测试环境再难搭建也要搭建出来调试代码
    00 alv抬头等
    流水号生产后调用
    ALV 顶栏的按钮设定
    Redis学习总结
    Mybatis总结
    面试题收集
    java 收集2
    关于Spring的69个面试问答——终极列表
    java 面试收集
  • 原文地址:https://www.cnblogs.com/zhangleo/p/9756492.html
Copyright © 2011-2022 走看看