您的位置:首页 > 其它

[2017雅礼集训]day2 T2 二分图关键点&&博弈

2017-04-05 18:45 369 查看
首先看到棋盘就要想到二分图模型。

建出二分图,考虑求出了一个最大匹配,假如Alice把棋放在一个未匹配点上,Bob无论如何都会走到一个匹配点上,然后Alice每次都可以选择走匹配边,直到Bob输。

所以只要求出这个图的所有非关键点(存在一种最大匹配不包含该点),都是Alice的必胜点。

求非关键点的方法:先求出最大匹配,首先对一侧,所有未匹配点能走交错路到的点都是非关键点,在对另一侧做同样的操作。

代码:

type
edge=^edgenode;
edgenode=record
t:longint;
next:edge;
end;

var
n,m,i,j,ans:longint;
c:char;
b,visit,unkey:array[0..10100]of boolean;
link:array[0..10100]of longint;
con:array[0..10100]of edge;
procedure ins(x,y:longint);
var
p:edge;
begin
if b[x] and b[y]=false then exit;
new(p);
p^.t:=y;
p^.next:=con[x];
con[x]:=p;

new(p);
p^.t:=x;
p^.next:=con[y];
con[y]:=p;
end;
function pipei(x:longint):boolean;
var
p:edge;
begin
pipei:=false;
p:=con[x];
while p<>nil do
begin
if visit[p^.t]=false then
begin
visit[p^.t]:=true;
if (link[p^.t]=-1)or(pipei(link[p^.t])=true) then begin link[p^.t]:=x; exit(true); end;
end;
p:=p^.next;
end;
end;
procedure dfs(v:longint);
var
p:edge;
begin
if v=-1 then exit;
visit[v]:=true;
unkey[v]:=true;
inc(ans);
p:=con[v];
while p<>nil do
begin
if (link[v]<>p^.t)and(link[p^.t]<>-1)and(visit[link[p^.t]]=false) then dfs(link[p^.t]);
p:=p^.next;
end;
end;
begin
readln(n,m);
for i:=1 to n*m do
begin
read(c);
if c='#' then b[i]:=false
else b[i]:=true;
if i mod m=0 then readln;
end;
for i:=1 to n*m do
begin
if i mod m<>1 then ins(i,i-1);
if i mod m<>0 then ins(i,i+1);
if i-m>0 then ins(i,i-m);
if i+m<=n*m then ins(i,i+m);
end;
for i:=1 to n*m do
link[i]:=-1;
for i:=1 to n*m do
if ((i-1) div m+(i-1) mod m)mod 2=0 then
begin
fillchar(visit,sizeof(visit),false);
pipei(i);
end;
for i:=1 to n*m do
if link[i]<>-1 then link[link[i]]:=i;

fillchar(unkey,sizeof(unkey),false);
fillchar(visit,sizeof(visit),false);
ans:=0;
for i:=1 to n*m do
if (b[i]=true)and(link[i]=-1)and(visit[i]=false) then dfs(i);
writeln(ans);
for i:=1 to n*m do
if (unkey[i]=true)and(b[i]=true) then writeln((i-1) div m+1,' ',(i-1) mod m+1);
readln;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: