图论 二分图最大独立集 最大流
骑士共存问题
«问题描述:
在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘
上某些方格设置了障碍,骑士不得进入。
«编程任务:
对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑
士,使得它们彼此互不攻击。
«数据输入:
由文件knight.in给出输入数据。第一行有2 个正整数n 和m (1<=n<=200, 0<=m<=n*n)<n2),< span="">
分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障
碍的方格坐标。
«结果输出:
将计算出的共存骑士数输出到文件knight.out。
输入文件示例 输出文件示例
knight.in
3 2
1 1
3 3
knight.out
5
二分图最大独立集,转化为二分图最大匹配,从而用最大流解决。
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cstring>
5 #include<queue>
6 #include<vector>
7 using namespace std;
8 const int mx[9]={0,1,1,-1,-1,2,2,-2,-2};
9 const int my[9]={0,2,-2,2,-2,1,-1,1,-1};
10 const int mxn=42000;
11 int read(){
12 int x=0,f=1;char ch=getchar();
13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14 while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
15 return x*f;
16 }
17 struct edge{int v,nxt,f;}e[mxn<<4];
18 int hd[mxn],mct=1;
19 void add_edge(int u,int v,int f){
20 e[++mct].v=v;e[mct].f=f;e[mct].nxt=hd[u];hd[u]=mct;return;
21 }
22 int n,m;
23 int S,T;
24 int d[mxn];
25 int id[210][210];
26 int mp[210][210];
27 bool BFS(int s,int t){
28 queue<int>q;
29 memset(d,0,sizeof d);
30 d[s]=1;
31 q.push(s);
32 while(!q.empty()){
33 int u=q.front();q.pop();
34 for(int i=hd[u];i;i=e[i].nxt){
35 int v=e[i].v;
36 if(!d[v] && e[i].f){
37 d[v]=d[u]+1;
38 q.push(v);
39 }
40 }
41 }
42 return d[t];
43 }
44 int DFS(int u,int lim){
45 if(u==T)return lim;
46 int tmp,f=0;
47 for(int i=hd[u];i;i=e[i].nxt){
48 int v=e[i].v;
49 if(d[v]==d[u]+1 && e[i].f){
50 tmp=DFS(v,min(lim,e[i].f));
51 e[i].f-=tmp;
52 e[i^1].f+=tmp;
53 lim-=tmp;
54 f+=tmp;
55 if(!lim)return f;
56 }
57 }
58 d[u]=0;
59 return f;
60 }
61 inline int Dinic(){
62 int res=0;
63 while(BFS(S,T))res+=DFS(S,1e9);
64 return res;
65 }
66 void solve(){
67 int i,j;
68 for(i=1;i<=n;i++)
69 for(j=1;j<=n;j++)
70 id[i][j]=(i-1)*n+j;
71 for(i=1;i<=n;i++)
72 for(j=1;j<=n;j++){
73 if(mp[i][j])continue;
74 if((i+j)%2==0)//白色
75 {
76 add_edge(S,id[i][j],1);
77 add_edge(id[i][j],S,0);
78 for(int k=1;k<=8;k++){
79 int nx=i+mx[k],ny=j+my[k];
80 if(nx<1 || nx>n || ny<1 || ny>n || mp[nx][ny])continue;
81 add_edge(id[i][j],id[nx][ny],1);
82 add_edge(id[nx][ny],id[i][j],0);
83 }
84 }
85 else{//黑色
86 add_edge(id[i][j],T,1);
87 add_edge(T,id[i][j],0);
88 }
89 }
90 return;
91 }
92 int main()
93 {
94 freopen("knight.in","r",stdin);
95 freopen("knight.out","w",stdout);
96 n=read();m=read();
97 int i,j,u,v;
98 for(i=1;i<=m;i++){
99 u=read();v=read();
100 mp[u][v]=1;//标记障碍
101 }
102 S=0;T=n*n+1;
103 solve();
104
105 int ans=Dinic();
106 ans=n*n-m-ans;
107 printf("%d\n",ans);
108 return 0;
109 }
本文为博主原创文章,转载请注明出处。