【题目描述】
在Cai0715的世界里,总共有N个城市,每两个城市之间都被一条无向的道路连接。
某一天,Boboo来Cai0715的世界游玩,由于这个世界太过于神奇,使他产生了一种环游世界的冲动,但他必须按照下面的规则进行环游。
·他必须在一个城市开始环游,在另一个世界结束环游。
·他环游世界时必须经过所有的城市一次,且只能经过一次。
·他环游世界时必须经过N-1条道路,且只能经过N-1条道路。
·由于某些道路的风景非常漂亮,所以Boboo想要在他环游世界的过程中必须经过这些道路。
现在,给定你一些必须经过的道路,问Boboo环游世界的方案有多少种?
【输入格式】
第一行,一个数N,代表共有N个城市。
以下是一个N行N列的字符矩阵A,如果A[I][J]是Y则代表城市I和城市J之间这条道路必须被经过。
【输出格式】
一行,一个数,Boboo环游世界的方案数。由于最后答案可能很大,所以只需要将答案mod 1000000007 输出即可。
【输入样例】
3
NYN
YNN
NNN
【输出样例】
4
思路
这个一看就知道是数学问题:排列组合。
首先,有一些点是必须按一定顺序排列的。于是,对于指定线路的点,我们找到它们,将它们视为一条链。设这样的缩过的点有x个;
其它没有限制的点,设有y个。
于是总共有A(x+y,x+y)种排列。但因为对于有限制的链倒过来走也是一样的,有2^x,所以,总共的方案数应有A(x+y,x+y)*2^x种。
此题的重点是在判断是否有环,如果它给的必走的路成环,那就呵呵了~~~
当然,根据欧拉回路的有关知识,一个点最多只能与两个点相连。如果一个点与3个及以上的点相连,那方案数为0。
下面代码中根本不用快速幂。。。只是有点闲
代码
const mmm=1000000007;
var x,y,n,i,j:longint;
ans:int64;
a:array[1..50,1..50]of char;
v:array[1..50]of boolean;
link:array[1..50]of integer;
procedure dfs(x:integer);
var i:integer;
begin
v[x]:=true;
for i:=1 to n do
if (a[x,i]='Y')and(not v[i]) then dfs(i);
end;
function pai(n:integer):int64;
begin
if (n=0)or(n=1)then exit(1);
if n=2 then exit(2);
pai:=(pai(n-1)*n)mod mmm;
end;
function mi(b:integer):int64;
var a,ans:longint;
begin
if b=0 then exit(1);
a:=2; ans:=1;
while b>0 do
begin
if (b and 1)=1 then ans:=(ans*a)mod mmm;
b:=b shr 1;
a:=(a*a)mod mmm;
end;
exit(ans);
end;
begin
assign(input,'travel.in');
assign(output,'travel.out');
reset(input);
rewrite(output);
readln(n);
for i:=1 to n do
for j:=1 to n do
if j=n then readln(a[i,j]) else read(a[i,j]);
for i:=1 to n do
for j:=1 to n do
if a[i,j]='Y' then inc(link[i]);
x:=0;y:=0;
for i:=1 to n do
begin
if link[i]=0 then inc(y); //统计孤立的没有限制的点
if link[i]>2
then begin write(0);close(input);close(output);halt;end;
end;
for i:=1 to n do
if (not v[i])and(link[i]=1) //满足此条件,说明点i是一条链的端点
then begin dfs(i);inc(x);end;//统计链的条数,并把每条链都访问一遍,为下面判断是否有环作准备
for i:=1 to n do
if (not v[i])and(link[i]>0) //满足此条件,那link【i】只能=2,即是有环存在的情况。因为在链中间的link【i】=2都已经被访问过了
then begin write(0);close(input);close(output);halt;end;
write(((pai(x+y) mod mmm)*(mi(x) mod mmm))mod mmm);
close(input);
close(output);
end.