• P3355 骑士共存问题


    (color{#0066ff}{题目描述})

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

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

    (color{#0066ff}{输入格式})

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

    (color{#0066ff}{输出格式})

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

    (color{#0066ff}{输入样例})

    3 2
    1 1
    3 3
    

    (color{#0066ff}{输出样例})

    5
    

    (color{#0066ff}{数据范围与提示})

    nothing

    (color{#0066ff}{题解})

    最大流等于最小割定理

    合法情况下,总情况-不成立情况=成立情况

    因为最小割等于最大流,所以找到不成立情况的最大流

    就得到了答案

    现在我们要找不合法情况的最大流

    考虑上图的红黄点,一个红点被占据,只会影响黄点,黄点同理

    因此,S向所有红点连容量为 1 的边

    所用红点向其影响的黄点连容量为 inf 的边(保证被影响,求出所有不合法情况

    所有黄点向T连容量为 1 的边

    答案就是n*n-m-最大流

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #define _ 0
    #define LL long long
    inline LL in()
    {
        LL x=0,f=1; char ch;
        while(!isdigit(ch=getchar()))(ch=='-')&&(f=-f);
        while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
        return x*f;
    }
    const int inf=0x7fffffff;
    struct node{int to,nxt,dis;}e[1050050];
    int rx[]={-2,-2,-1,-1,1,1,2,2};
    int ry[]={-1,1,-2,2,-2,2,-1,1};
    int cnt=1,n,m,s,t;
    std::queue<int> q;
    int head[505005],cur[505005],dep[500505];
    bool mp[250][250];
    inline int getid(int x,int y) {return (x-1)*n+y;}
    inline void add(int from,int to,int dis)
    {
    	cnt++;
    	e[cnt].to=to;
    	e[cnt].dis=dis;
    	e[cnt].nxt=head[from];
    	head[from]=cnt;
    }
    inline void expand(int x,int y)
    {
    	for(int i=0;i<8;i++)
    	{
    		int xx=x+rx[i];
    		int yy=y+ry[i];
    		if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!mp[xx][yy])
    		{
    			add(getid(x,y),getid(xx,yy),inf);
    			add(getid(xx,yy),getid(x,y),0);
    		}
    	}
    }
    inline bool bfs()
    {
    	for(int i=s;i<=t;i++) dep[i]=0,cur[i]=head[i];
    	q.push(s);
    	dep[s]=1;
    	while(!q.empty())
    	{
    		int tp=q.front(); q.pop();
    		for(int i=head[tp];i;i=e[i].nxt)
    		{
    			int go=e[i].to;
    			if(!dep[go]&&e[i].dis>0)
    			{
    				dep[go]=dep[tp]+1;
    				q.push(go);
    			}
    		}
    	}
    	return dep[t];
    }
    inline int dfs(int x,int change)
    {
    	if(x==t||!change) return change;
    	int flow=0,ls;
    	for(int i=cur[x];i;i=e[i].nxt)
    	{
    		int go=e[i].to;
    		cur[x]=i;
    		if(dep[go]==dep[x]+1&&(ls=dfs(go,std::min(change,e[i].dis))))
    		{
    			change-=ls;
    			flow+=ls;
    			e[i].dis-=ls;
    			e[i^1].dis+=ls;
    			if(!change) break;
    		}
    	}
    	return flow;
    }
    inline int dinic()
    {
    	int flow=0;
    	while(bfs()) flow+=dfs(s,inf);
    	return flow;
    }
    int main()
    {
    	n=in(),m=in();
    	t=n*n+1,s=0;
    	int x,y;
    	for(int i=1;i<=m;i++)
    	{
    		x=in(),y=in();
    		mp[x][y]=true;
    	}
    	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
    	{
    		if(mp[i][j]) continue;
    		if((i+j)&1)
    		{
    			add(s,getid(i,j),1);
    			add(getid(i,j),s,0);
    			expand(i,j);
    		}
    		else add(getid(i,j),t,1),add(t,getid(i,j),0);
    	}
    	printf("%d",n*n-m-dinic());
    	return 0;
    }
    
  • 相关阅读:
    ubuntu16.04安装破解pycharm
    python解压,压缩,以及存数据库的相关操作
    cocoapods Error
    swift项目导入OC框架
    实现全屏滑动返回效果
    Storyboard & XIB 自己的理解
    View & Controller 一些方法的执行顺序
    Touch ID 实现
    Apple Pay 初探
    ReactiveCocoa学习
  • 原文地址:https://www.cnblogs.com/olinr/p/10101907.html
Copyright © 2020-2023  润新知