环游世界

【题目描述】

在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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值