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

    题面戳我
    题目描述
    在一个 nn个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入
    对于给定的 n
    n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击
    输入输出格式
    输入格式:
    第一行有 2 个正整数n 和 m ((1<=n<=200, 0<=m<n^2)),分别表示棋盘的大小和障碍数。接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。
    输出格式:
    将计算出的共存骑士数输出
    输入输出样例
    输入样例#1:

    3 2
    1 1
    3 3
    

    输出样例#1:

    5
    

    sol

    这题其实就是【网络流24题9】方格取数问题的弱化版。
    还是最大独立集=(sum)点权-最小顶点覆盖,然后二分图最小顶点覆盖=最小割=最大流
    注意到这里的最大流其实就是二分图匹配数,然后你写一个匈牙利上去就会T,会T,T。。。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define inf 1000000000
    const int _ = 205;
    struct edge{int to,next,w;}a[_*_*10];
    int n,m,s,t,map[_][_],head[_*_],cnt=1,dep[_*_],cur[_*_],sum,ans;
    int dx[8]={1,2,2,1,-1,-2,-2,-1},dy[8]={2,1,-1,-2,-2,-1,1,2};
    queue<int>Q;
    void link(int u,int v,int w)
    {
    	a[++cnt]=(edge){v,head[u],w};
    	head[u]=cnt;
    	a[++cnt]=(edge){u,head[v],0};
    	head[v]=cnt;
    }
    bool bfs()
    {
    	memset(dep,0,sizeof(dep));
    	dep[s]=1;Q.push(s);
    	while (!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].next)
    			if (a[e].w&&!dep[a[e].to])
    				dep[a[e].to]=dep[u]+1,Q.push(a[e].to); 
    	}
    	return dep[t];
    }
    int dfs(int u,int flow)
    {
    	if (u==t)
    		return flow;
    	for (int &e=cur[u];e;e=a[e].next)
    		if (a[e].w&&dep[a[e].to]==dep[u]+1)
    		{
    			int temp=dfs(a[e].to,min(flow,a[e].w));
    			if (temp) {a[e].w-=temp;a[e^1].w+=temp;return temp;}
    		}
    	return 0;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);s=n*n+1;t=s+1;
    	for (int i=1,x,y;i<=m;i++)
    		scanf("%d%d",&x,&y),map[x][y]=1;
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    		{
    			if (map[i][j]) continue;
    			if ((i+j)&1)
    			{
    				link(s,n*i-n+j,1);
    				for (int k=0;k<8;k++)
    				{
    					int nx=i+dx[k],ny=j+dy[k];
    					if (nx<1||nx>n||ny<1||ny>n||map[nx][ny]) continue;
    					link(n*i-n+j,n*nx-n+ny,inf);
    				}
    			}
    			else link(n*i-n+j,t,1);
    		}
    	while (bfs())
    	{
    		for (int i=t;i;i--) cur[i]=head[i];
    		while (int temp=dfs(s,inf)) ans+=temp;
    	}
    	printf("%d
    ",n*n-m-ans);
    	return 0;
    } 
    
  • 相关阅读:
    jupytr notebook远程登录Linux服务器,切换conda虚拟环境
    Linux 命令su 和 su -执行机制的区别
    Shell编程知识4-su详细
    Shell编程知识3
    Shell编程知识2
    Ubuntu # echo $PATH //查看当前用户的环境变量--》修改配置环境变量
    Util和Helper类
    Qt QBarSeries简易柱状图教程
    解决QIcon引用qrc不显示图片
    qt调用quit()后未结束线程解决方案
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8191926.html
Copyright © 2011-2022 走看看