Description
你突然有了一个大房子,房子里面有一些房间。事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子。在一开始的时候,相邻的格子之间都有墙隔着。
你想要打通一些相邻房间的墙,使得所有房间能够互相到达。在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙)。同时,你不希望在房子中有小偷的时候会很难抓,所以你希望任意两个房间之间都只有一条通路。现在,你希望统计一共有多少种可行的方案。
基尔霍夫矩阵树定理裸题...
const
mo=1000000000;
walk:array[1..4,1..2] of longint=((1,0),(-1,0),(0,1),(0,-1));
var
n,m,tot,tx,ty :longint;
i,j,k :longint;
s :string;
map :array[0..110,0..110] of char;
a,num :array[0..110,0..110] of int64;
procedure swap(var a,b:int64);
var
c:int64;
begin
c:=a; a:=b; b:=c;
end;
function matrix_tree(n:longint):int64;
var
i,j,k:longint;
ret,tt:int64;
begin
ret:=1;
for i:=1 to n do
begin
for j:=i+1 to n do
begin
while a[j,i]<>0 do
begin
tt:=a[i,i] div a[j,i];
for k:=i to n do a[i,k]:=(a[i,k]-tt*a[j,k]+mo) mod mo;
for k:=i to n do swap(a[i,k],a[j,k]);
ret:=-ret;
end;
end;
if a[i,i]=0 then exit(0);
ret:=(ret*a[i,i]) mod mo;
end;
if ret<0 then ret:=(ret+mo) mod mo;
exit(ret);
end;
begin
readln(n,m);
for i:=1 to n do
begin
readln(s);
for j:=1 to m do map[i,j]:=s[j];
end;
tot:=0;
for i:=1 to n do
for j:=1 to m do
if map[i,j]='.' then
begin
inc(tot); num[i,j]:=tot;
end;
for i:=1 to n do
for j:=1 to m do
for k:=1 to 4 do
begin
tx:=i+walk[k,1]; ty:=j+walk[k,2];
if (tx<0) or (ty<0) or (tx>n) or (ty>m) then continue;
if map[tx,ty]<>'.' then continue;
inc(a[num[i,j],num[i,j]]);
a[num[i,j],num[tx,ty]]:=-1;
end;
for i:=1 to tot do
for j:=1 to tot do
if a[i,j]<0 then a[i,j]:=(a[i,j]+mo) mod mo;
writeln(matrix_tree(tot-1));
end.
——by Eirlys