骑士共存问题 二分图的最大独立集
来源:互联网 发布:java数据类型取值范围 编辑:程序博客网 时间:2024/05/16 17:49
题目描述 Description
在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘
上某些方格设置了障碍,骑士不得进入。
对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑
士,使得它们彼此互不攻击。
输入描述 Input Description
第一行有2 个正整数n 和m (1<=n<=200, 0<=m<n^2),
分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障
碍的方格坐标。
输出描述 Output Description
将计算出的共存骑士数输出
样例输入 Sample Input
3 2
1 1
3 3
样例输出 Sample Output
5
数据范围及提示 Data Size & Hint
题目可以在这里提交:http://wikioi.com/homework/23/详见试题
分析:二分图的最大独立集,可以先求二分图的最大匹配,简单建图。
代码:
//Isap算法,复杂度O(n^2m)#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll; //记得必要的时候改成无符号const int maxn=100005;const int maxm=1000005;const int INF=1000000000;struct EdgeNode{ int from; int to; int cost; int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y,int z){ edge[cnt].from=x;edge[cnt].to=y;edge[cnt].cost=z;edge[cnt].next=head[x];head[x]=cnt++; edge[cnt].from=y;edge[cnt].to=x;edge[cnt].cost=0;edge[cnt].next=head[y];head[y]=cnt++; //printf("%d %d %d\n",x,y,z);}void init(){ cnt=0; memset(head,-1,sizeof(head));}int S,T,n,m;int d[maxn],gap[maxn],curedge[maxn],pre[maxn];//curedge[]为当前弧数组,pre为前驱数组int sap(int S,int T,int n) //n为点数{ int cur_flow,flow_ans=0,u,tmp,neck,i; memset(d,0,sizeof(d)); memset(gap,0,sizeof(gap)); memset(pre,-1,sizeof(pre)); for(i=0;i<=n;i++)curedge[i]=head[i]; //初始化当前弧为第一条邻接表 gap[0]=n; u=S; while(d[S]<n) //当d[S]>=n时,网络中肯定出现了断层 { if(u==T) { cur_flow=INF; for(i=S;i!=T;i=edge[curedge[i]].to) { //增广成功,寻找瓶颈边 if(cur_flow>edge[curedge[i]].cost) { neck=i; cur_flow=edge[curedge[i]].cost; } } for(i=S;i!=T;i=edge[curedge[i]].to) { //修改路径上的边容量 tmp=curedge[i]; edge[tmp].cost-=cur_flow; edge[tmp^1].cost+=cur_flow; } flow_ans+=cur_flow; u=neck; //下次增广从瓶颈边开始 } for(i=curedge[u];i!=-1;i=edge[i].next) if(edge[i].cost&&d[u]==d[edge[i].to]+1) break; if(i!=-1) { curedge[u]=i; pre[edge[i].to]=u; u=edge[i].to; } else { if(0==--gap[d[u]])break; //gap优化 curedge[u]=head[u]; for(tmp=n,i=head[u];i!=-1;i=edge[i].next) if(edge[i].cost) tmp=min(tmp,d[edge[i].to]); d[u]=tmp+1; ++gap[d[u]]; if(u!=S)u=pre[u]; //重标号并且从当前点前驱重新增广 } } return flow_ans;}bool mp[205][205];int dis[9][3]={{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1},{2,1},{1,2}};int yj(int x,int y){ if(x<1||x>n||y<1||y>n)return 1; return 0;}int build(){ int i,j,k,x,y,a,b,s=0; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(mp[i][j])continue; s++; a=(i-1)*n+j; add(S,a,1); add(a+n*n,T,1); } } for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(mp[i][j])continue; a=(i-1)*n+j; for(k=0;k<8;k++){ x=i+dis[k][0]; y=j+dis[k][1]; if(!yj(x,y)&&!mp[x][y]){ b=(x-1)*n+y; add(a,b+n*n,1); } } } } return s;}int main(){ int i,j,x,y,sum; while(~scanf("%d%d",&n,&m)) { init(); S=0; T=2*n*n+1; memset(mp,0,sizeof(mp)); for(i=1;i<=m;i++){ scanf("%d%d",&x,&y); mp[x][y]=1; } sum=build(); printf("%d\n",sum-sap(S,T,T+1)/2); } return 0;}
0 0
- 骑士共存问题 二分图的最大独立集
- [网络流24题][codevs1922] 骑士共存问题 二分图最大独立集
- [网络流24题]骑士共存问题 二分图/最大点权独立集
- codevs 1922 骑士共存问题||二分图||最大独立集||二分图匹配||Dinic与匈牙利算法的讨论||网络流
- 线性规划与网络流24题の24 骑士共存问题 (二分图最大独立集)
- loj6226「网络流 24 题」骑士共存问题(二分图最大点独立集,最小割)
- 【网络流二十四题 骑士共存问题】【二分图点权最大独立集->最小割】
- [网络流24题] 24 骑士共存(二分图最大独立集,网络最小割)
- wikioi 1922 骑士共存问题 最大独立集
- NKOJ-1569 骑士共存 <最大独立集><染色法建图>
- 骑士共存问题 (二分图最大匹配 转换 网络最大流 )
- Codevs_P1922 骑士共存问题(Dinic算法最大流+二分图匹配)
- 【网络流24题】骑士共存问题(二分图染色+最大权独立子集+最小割)
- 最大独立集问题 二分图
- 【学校OJ】二分图匹配 骑士共存问题
- 【COGS】746 [网络流24题] 骑士共存 最大独立集
- 网络流24题之二十四 骑士共存 最大独立集
- Cogs 746. [网络流24题] 骑士共存(最大独立集)
- 保存所有系统变量的方法
- 30 HTML CSS HTTP
- 9patch使用,图片自适应
- 服务器的压力测试
- Invalid Bundle Structure - The binary file '***.app/***.a' is not permitted
- 骑士共存问题 二分图的最大独立集
- android如何实现环形缓冲区
- error:unknown filesystem grub rescue
- 当两台LINUX主机之间要互传文件时可使用SCP命令来实现
- PID217 线性DP
- 关于数据可视化的一些总结
- Bigdecimal 精度
- Yale开放课程博弈论7
- 我只能送你笑话了