zoukankan      html  css  js  c++  java
  • [网络流24题]骑士共存问题

    题目:洛谷P3355、codevs1922。

    题目大意:在n*n的国际象棋棋盘上,有一些障碍点,这些障碍点不能放任何东西。现在要在棋盘没障碍的地方放置骑士(马),问最多能放多少个,使它们不互相攻击?

    解题思路:最小割问题。

    此题同“方格取数问题”思路相同。

    由于马攻击到的点和它所在点的颜色必然不相同,那么我们将棋盘黑白染色,黑的连源点,白的连汇点,容量1。然后黑点连接能攻击到的白点,容量无穷大。

    如果是障碍点,则不连边。

    最后求最大流,再用总数减去障碍数减去最大流即可。

    注意数组开够。

    C++ Code:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3fffffff
    std::queue<int>q;
    int n,m,cnt=-1,head[70005],iter[70005],level[70005];
    bool b[205][205];
    int dx[]={0,2,1,-2,1,2,-1,-2,-1},
        dy[]={0,1,2,1,-2,-1,2,-1,-2};
    struct edge{
        int to,cap,nxt;
    }e[40005*10];
    inline int number(int x,int y){
        return(x-1)*n+y;
    }
    inline void addedge(int from,int to,int flow){
        ++cnt;
        e[cnt]=(edge){to,flow,head[from]};
        head[from]=cnt;
        ++cnt;
        e[cnt]=(edge){from,0,head[to]};
        head[to]=cnt;
    }
    void bfs(int s){
        level[s]=1;
        q.push(s);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=e[i].nxt)
            if(e[i].cap&&level[e[i].to]==-1){
                level[e[i].to]=level[u]+1;
                q.push(e[i].to);
            }
        }
    }
    int dfs(int u,int t,int f){
        if(u==t)return f;
        for(int& i=iter[u];i!=-1;i=e[i].nxt)
        if(e[i].cap&&level[u]<level[e[i].to]){
            int d=dfs(e[i].to,t,e[i].cap>f?f:e[i].cap);
            if(d){
                e[i].cap-=d;
                e[i^1].cap+=d;
                return d;
            }
        }
        return 0;
    }
    int maxflow(int s,int t){
        for(int flow=0;;){
            memset(level,-1,sizeof level);
            bfs(s);
            if(level[t]==-1)return flow;
            memcpy(iter,head,sizeof iter);
            int f;
            while(f=dfs(s,t,inf))flow+=f;
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        memset(b,0,sizeof b);
        for(int i=1;i<=m;++i){
        	int x,y;
        	scanf("%d%d",&x,&y);
        	b[x][y]=true;
        }
        memset(head,-1,sizeof head);
        for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j){
        	if(b[i][j])continue;
            int p=number(i,j);
            if((i+j)&1){
                addedge(0,p,1);
                for(int h=1;h<9;++h){
                	int x=dx[h]+i,y=dy[h]+j;
                	if(x>0&&y>0&&x<=n&&y<=n&&!b[x][y])addedge(p,number(x,y),inf);
                }
            }else addedge(p,n*n+1,1);
        }
        return!printf("%d
    ",n*n-m-maxflow(0,n*n+1));
    }
  • 相关阅读:
    Ubuntu20安装docker
    ubuntu 下mysql 大小写问题
    Tensorflow-常见报错解决方案
    迁移学习(Transfer Learning)
    c#的托管代码和非托管代码的理解
    .net面试题升级版
    ADO.NET知识点
    支持“WeShopDb”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库
    .net 面试题
    6、zookeeper应用场景-分布式唯一ID
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8305649.html
Copyright © 2011-2022 走看看