bzoj 4031 矩阵树定理

61 篇文章 0 订阅
2 篇文章 0 订阅

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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值