• [网络流24题]骑士共存问题


    题目描述

    二分图最大点独立集问题。

    要求在棋盘上放最多互不攻击的骑士,即在棋盘中拿走最少的骑士,使得剩下的骑士互不攻击。

    黄格只能攻击红格,红格也只能攻击黄格,所以考虑建立二分图。

    源点向所有红格连流量为1的边,所有黄格向汇点连流量为一的边,再由红格向它能攻击到的黄格连流量为1的边,有障碍物的点不连边。

    每找到一条增广路,即从棋盘中拿走一个骑士,所以最后的答案就是总点数-障碍数-最大匹配数。

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int N=4e4+7;
    const int dx[]={-1,-1,1,1,-2,-2,2,2},dy[]={-2,2,-2,2,-1,1,-1,1};
    struct node{
        int v,f,nxt;
    }e[N*10];
    int n,m,Enum=1,s,t;
    int front[N],cur[N],deep[N];
    int q[N];
    bool vis[201][201];
    int qread()
    {
        int x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9')ch=getchar();
        while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    void Insert(int u,int v,int w)
    {
        e[++Enum].v=v;e[Enum].f=w;e[Enum].nxt=front[u];front[u]=Enum;
        e[++Enum].v=u;e[Enum].f=0;e[Enum].nxt=front[v];front[v]=Enum;
    }
    bool bfs()
    {
        for(int i=0;i<=t;i++)
        {
            deep[i]=0;
            cur[i]=front[i];
        }
        int head=1,tail=0,u,v;
        deep[s]=1;q[++tail]=s;
        while(head<=tail)
        {
            u=q[head++];
            for(int i=front[u];i;i=e[i].nxt)
            {
                v=e[i].v;
                if(!deep[v] && e[i].f)
                {
                    deep[v]=deep[u]+1;
                    if(v==t)return 1;
                    q[++tail]=v;
                }
            }
        }
        return 0;
    }
    int dfs(int x,int cur_flow)
    {
        if(x==t)return cur_flow;
        int rest=cur_flow,v;
        for(int &i=cur[x];i;i=e[i].nxt)
        {
            v=e[i].v;
            if(deep[v]==deep[x]+1 && e[i].f && rest)
            {
                int new_flow=dfs(v,min(e[i].f,rest));
                e[i].f-=new_flow;
                e[i^1].f+=new_flow;
                rest-=new_flow;
                if(!rest)return cur_flow;
            }
        }
        deep[x]=0;
        return cur_flow-rest;
    }
    int Dinic()
    {
        int res=0;
        while(bfs())
            res+=dfs(s,INF);
        return res;
    }
    bool can(int x,int y)
    {
        if(x<1 || x>n || y<1 || y>n || vis[x][y])return 0;
        return 1;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        s=0;t=n*n+1;
        for(int i=1;i<=m;i++)
            vis[qread()][qread()]=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(!vis[i][j])
                    if((i+j)&1)
                        Insert(s,(i-1)*n+j,1);
                    else Insert((i-1)*n+j,t,1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(!vis[i][j] && (i+j)&1)
                    for(int k=0;k<8;k++)
                    {
                        int xx=i+dx[k],yy=j+dy[k];
                        if(can(xx,yy))
                            Insert((i-1)*n+j,(xx-1)*n+yy,1);
                    }
        printf("%d
    ",n*n-m-Dinic());
        return 0;
    }
  • 相关阅读:
    JUnit测试类完成后事务是默认 回滚的。只能查询数据,不能增删改。
    linux每日命令(28):chgrp命令
    linux每日命令(27):chmod命令
    linux每日命令(26):Linux文件属性详解
    linux每日命令(25):Linux文件类型与扩展名
    linux每日命令(24):Linux 目录结构
    linux每日命令(23):find命令之xargs
    linux每日命令(22):find命令参数详解
    linux每日命令(21):find命令之exec
    linux每日命令(20):find命令概览
  • 原文地址:https://www.cnblogs.com/LeTri/p/9029989.html
Copyright © 2020-2023  润新知