zoukankan      html  css  js  c++  java
  • luogu P3355 骑士共存问题 |最大流

    题目描述

    在一个 (n*n)个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入

    对于给定的 (n*n) 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击

    输入格式

    第一行有 2 个正整数(n)(m) ((1<=n<=200, 0<=m<n^2)),分别表示棋盘的大小和障碍数。接下来的 (m) 行给出障碍的位置。每行 (2) 个正整数,表示障碍的方格坐标。

    输出格式

    将计算出的共存骑士数输出


    将棋盘上的点分成两类,求最小割

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define int long long
    #define ll long long
    #define re register int
    using namespace std;
    const int N=4e5+10,M=6e5+10,inf=1<<30;
    int n,m,s,t,maxflow;
    int nxt[M],head[N],go[M],edge[M],tot=1;
    inline void add(int u,int v,int o){
    	nxt[++tot]=head[u];head[u]=tot;go[tot]=v;edge[tot]=o;
    	nxt[++tot]=head[v];head[v]=tot;go[tot]=u;edge[tot]=0;	
    }
    int d[N];
    inline bool bfs(){
    	queue<int>q;
    	memset(d,0,sizeof(d));
    	q.push(s);d[s]=1;
    	while(q.size()){
    		int u=q.front();q.pop();
    		for(re i=head[u];i;i=nxt[i]){
    			int v=go[i];
    			if(edge[i]&&!d[v]){
    				q.push(v);
    				d[v]=d[u]+1;
    				if(v==t)return 1;
    			}
    		}
    	}
    	return 0;
    }
    inline int dinic(int u,int flow){
    	if(u==t)return flow;
    	int rest=flow,k;
    	for(re i=head[u];i&&rest;i=nxt[i]){
    		int v=go[i];
    		if(edge[i]&&d[v]==d[u]+1){
    			k=dinic(v,min(rest,edge[i]));
    			if(!k)d[v]=0;
    			edge[i]-=k;
    			edge[i^1]+=k;
    			rest-=k;
    		}
    	}
    	return flow-rest;
    }
    bool vis[205][205];
    inline int P(int x,int y){
        return (x-1)*n+y;
    }
    const int dx[8]={1,1,-1,-1,2,2,-2,-2},dy[8]={2,-2,2,-2,1,-1,1,-1}; 
    signed main(){
        cin>>n>>m; t=n*n+2;
        for(int i=1,x,y;i<=m;i++){
            scanf("%lld%lld",&x,&y);
            vis[x][y]=1;
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            if(!vis[i][j]){
                if((i+j)&1)add(s,P(i,j),1);
                else add(P(i,j),t,1);
            }
            if((i+j)&1)
            for(int k=0;k<8;k++){
                int x=i+dx[k],y=j+dy[k];
                if(x<1||y<1||x>n||y>n||vis[x][y])continue;
                add(P(i,j),P(x,y),inf);
            }
        }
    	int flow=0;
    	while(bfs())
    	while(flow=dinic(s,inf))maxflow+=flow;
    	cout<<n*n-m-maxflow<<endl;
    }
    
  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12206800.html
Copyright © 2011-2022 走看看