题意:
在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘
上某些方格设置了障碍,骑士不得进入。
对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击。
n<=200,m<=n^2
思路:经典的二分图最大独立集,采用黑白点染色的思想。
如果按照相邻点黑白不同染色,可以发现每次跳到的点必定与现在所在点不同色,二分图最大匹配即可。
每切断一条黑白点之间的边就是少放了一个骑士,用最小割算出最少要切断几条边,总数减去有障碍的再减切断的边数就是最大匹配数,最大独立集又可以转化为最大匹配数。
这里用最小割来解决,因为不能允许任何黑白点之间的任何一条边有流量,符合最小割的思想。
1 const dx:array[1..8]of longint=(-2,-2,-1,-1,1,1,2,2);
2 dy:array[1..8]of longint=(-1,1,-2,2,-2,2,-1,1);
3 var head,vet,next,len,fan,gap,dis:array[0..500000]of longint;
4 b,num,a:array[1..300,1..300]of longint;
5 n,m,i,tot,x,y,k,j,source,src,s:longint;
6
7 procedure add(a,b,c:longint);
8 begin
9 inc(tot);
10 next[tot]:=head[a];
11 vet[tot]:=b;
12 len[tot]:=c;
13 head[a]:=tot;
14 end;
15
16 function min(x,y:longint):longint;
17 begin
18 if x<y then exit(x);
19 exit(y);
20 end;
21
22 function dfs(u,aug:longint):longint;
23 var e,v,val,flow,t:longint;
24 begin
25 if u=src then exit(aug);
26 flow:=0; val:=s-1;
27 e:=head[u];
28 while e<>0 do
29 begin
30 v:=vet[e];
31 if len[e]>0 then
32 begin
33 if dis[u]=dis[v]+1 then
34 begin
35 t:=dfs(v,min(len[e],aug-flow));
36 len[e]:=len[e]-t;
37 len[fan[e]]:=len[fan[e]]+t;
38 flow:=flow+t;
39 if dis[source]>=s then exit(flow);
40 if aug=flow then break;
41 end;
42 val:=min(val,dis[v]);
43 end;
44 e:=next[e];
45 end;
46 if flow=0 then
47 begin
48 dec(gap[dis[u]]);
49 if gap[dis[u]]=0 then dis[source]:=s;
50 dis[u]:=val+1;
51 inc(gap[dis[u]]);
52 end;
53 exit(flow);
54 end;
55
56 function maxflow:longint;
57 var ans:longint;
58 begin
59 fillchar(gap,sizeof(gap),0);
60 fillchar(dis,sizeof(dis),0);
61 gap[0]:=s; ans:=0;
62 while dis[source]<s do ans:=ans+dfs(source,maxlongint);
63 exit(ans);
64 end;
65
66 begin
67 assign(input,'codevs1922.in'); reset(input);
68 assign(output,'codevs1922.out'); rewrite(output);
69 read(n,m);
70 for i:=1 to n do
71 for j:=1 to n do
72 begin
73 inc(s); a[i,j]:=(i+j+1) mod 2; num[i,j]:=s;
74 end;
75 for i:=1 to m do
76 begin
77 read(x,y);
78 b[x,y]:=1;
79 end;
80 s:=n*n+2;
81 for i:=1 to n do
82 for j:=1 to n do
83 if (a[i,j]=1)and(b[i,j]=0) then
84 begin
85 for k:=1 to 8 do
86 begin
87 x:=i+dx[k]; y:=j+dy[k];
88 if (x>0)and(x<=n)and(y>0)and(y<=n)and(b[x,y]=0) then
89 begin
90 fan[tot+2]:=tot+1;
91 fan[tot+1]:=tot+2;
92 add(num[i,j],num[x,y],1);
93 add(num[x,y],num[i,j],0);
94 end;
95 end;
96 end;
97 source:=50000; src:=50001;
98 for i:=1 to n do
99 for j:=1 to n do
100 if a[i,j]=1 then
101 begin
102 fan[tot+2]:=tot+1;
103 fan[tot+1]:=tot+2;
104 add(source,num[i,j],1);
105 add(num[i,j],source,0);
106 end
107 else if b[i,j]=0 then
108 begin
109 fan[tot+2]:=tot+1;
110 fan[tot+1]:=tot+2;
111 add(num[i,j],src,1);
112 add(src,num[i,j],0);
113 end;
114 writeln(n*n-m-maxflow);
115 close(input);
116 close(output);
117 end.