题意:我们有一个n*n的黑白(随意) 方阵,1表示黑色 0表示白色,我们可以选择任意两行进行交换 或 任意选择两列进行交换 ,使得方阵的主对角线均为黑色 ,判断局面是否有解
.....这他喵的是二分图匹配....
我们发现,对于同一行的多个1,无论如何我们也不能把它们同时移动到主对角线上(因为它们一定会在同一行,而同一行只有(i,i)能做出贡献),同理,对于同一列上的多个1我们也不能把它们同时移动到主对角线上
得出结论:在同一行或者同一列的1有且只能有1个动到主对角线上。
即只有不在同一行同一列的两个1我们才能将其都移动到主对角线上。
那么我们就需要找出n个两两不同行且不同列的1使得局面有解,否则无解
是不是有点像去掉对角线条件的八皇后?
然而只是有点像并不能借鉴其搜索的方法,因为我们可以改变我们已有的配对(让(i,j)的1到主对角线上的(x,x)位置)使尽量多的的1在主对角线上
是不是和匈牙利算法很像?没错,就是它~
====================我是理想与现实的分界线_(:з」∠)_======================
我们构造一张二分图,图的一边是行,另一边是列,对于每个黑点连边,二分图匹配即可
var
t,n :longint;
i,j :longint;
f :boolean;
map :array[0..210,0..210] of integer;
link :array[0..210] of longint;
flag :array[0..210] of boolean;
function find(x:longint):boolean;
var
i,j:longint;
begin
for i:=1 to n do
begin
if (map[x,i]=1) and (not flag[i]) then
begin
flag[i]:=true;
if (link[i]=0) or (find(link[i])) then
begin
link[i]:=x;
exit(true);
end;
end;
end;
exit(false);
end;
begin
read(t);
while (t>0) do
begin
dec(t);
fillchar(link,sizeof(link),0);
read(n);
f:=true;
for i:=1 to n do
for j:=1 to n do read(map[i,j]);
//
for i:=1 to n do
begin
fillchar(flag,sizeof(flag),false);
if not find(i) then
begin
f:=false;break;
end;
end;
//
if f then writeln('Yes') else writeln('No');
end;
end.
——by Eirlys