zoukankan      html  css  js  c++  java
  • 网络流24题——骑士共存问题 luogu 3355

    题目描述:这里

    从这里开始,我们涉及到了一个新的问题:最小割问题

    首先给出一些定义(本人根据定义自己口胡的):

    一个流网络中的一个割是一个边集,使得割掉这些边集后源点与汇点不连通

    而最小割问题就是一个使得边集中各边容量之和最小的割

    根据ford-fulkerson定理,最小割等于最大流!

    基于上面的定义,我们可以来讨论这道题了:

    首先,根据套路,棋盘经过黑白染色之后可以形成一个二分图,我们由源点向黑点连边,白点向汇点连边,然后由黑点向白点连边,权值为1(所有不能用的点不做考虑)

    然后跑一遍最小割,用总和减去最小割即可

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    using namespace std;
    const int inf=0x3f3f3f3f;
    struct Edge
    {
        int next;
        int to;
        int val;
    }edge[500005];
    int head[100005];
    int dir[8][2]={{2,1},{1,2},{1,-2},{2,-1},{-1,-2},{-2,-1},{-1,2},{-2,1}};
    bool used[2005][2005];
    int dis[100005];
    int cur[100005];
    int cnt=1;
    int n,m;
    int st,ed;
    void init()
    {
        memset(head,-1,sizeof(head));
        cnt=1;
    }
    void add(int l,int r,int w)
    {
        edge[cnt].next=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    bool check(int x,int y)
    {
        return (x>=1)&&(x<=n)&&(y>=1)&&(y<=n)&&(!used[x][y]);
    }
    int ide(int x)
    {
        return (x&1)?x+1:x-1;
    }
    int idx(int x,int y)
    {
        return (x-1)*n+y;
    }
    bool bfs()
    {
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        dis[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int to=edge[i].to;
                if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[ed];
    }
    int dfs(int x,int lim)
    {
        if(x==ed)return lim;
        int ret=0;
        for(int i=cur[x];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                int temp=dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    lim-=temp;
                    ret+=temp;
                    edge[i].val-=temp;
                    edge[ide(i)].val+=temp;
                    if(!lim)break;
                }
            }
            cur[x]=i;
        }
        return ret;
    }
    int dinic()
    {
        int ret=0;
        while(bfs())ret+=dfs(st,inf);
        return ret;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        st=n*n+1,ed=n*n+2;
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            used[x][y]=1;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(used[i][j])continue;
                if((i+j)&1)
                {
                    add(st,idx(i,j),1);
                    add(idx(i,j),st,0);
                    for(int k=0;k<8;k++)
                    {
                        int x=i+dir[k][0];
                        int y=j+dir[k][1];
                        if(check(x,y))add(idx(i,j),idx(x,y),inf),add(idx(x,y),idx(i,j),0);
                    }
                }else
                {
                    add(idx(i,j),ed,1);
                    add(ed,idx(i,j),0);
                }
            }
        }
        printf("%d
    ",n*n-m-dinic());
        return 0;
    }
  • 相关阅读:
    .net 设置默认首页
    MySQL如何对数据库状态值指定排序
    golang将mm-dd-yy的字符串转时间格式
    Nginx文件解析
    Git使用笔记
    批量导入实现逻辑
    golang字符串截取
    golang格式化代码
    golang获取某一年某一月份的开始日期和结束日期
    nslookup install
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10774425.html
Copyright © 2011-2022 走看看