SCOI2009 迷路

有向图有 N 个节点,从节点 0 出发,必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,总共有多少种不同的路径

注意:不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。

用矩阵乘法把n个01邻接矩阵(连通性矩阵,a[i,j]=1表示 i 到 j 有一条有向边相连),则a[i,j]就表示走n步后从i到j的不同的路的条数。由于题目中边有权,而权值只是1..9,所以可以把每个点拆成9个点,即第i个点变成第9*(i-1)+1到第9*(i-1)+9个点,把这n个点各自拆出来的9个点串连

即a[9*(i-1)+j,9*(i-1)+j+1]:=1(1<=j<=8),读入邻接矩阵时i到j权值是k,就从9*(i-1)+k往9*(j-1)+1上连一条边,用矩阵乘法快速幂在logN的时间内求出a^N,则a[1,9*(n-1)+1]为解。

这个程序写的有些烂,数据在1.0x s出解,自己看着优化下常数,写递归快速幂还爆栈。。

 

改改改。。。。。。

 

终于发现问题了,数组开成integer就0.1出解了,没想到int64那么慢。

View Code
 1 {$inline on}
 2 program road(input,output);
 3 type
 4    numbertype=array[0..91,0..91] of integer;//就这里,写成int64过不了
 5 var 
 6    map        : array[0..11,0..11] of integer;
 7    power    : array[0..30] of numbertype;
 8    v        : array[0..30] of boolean;
 9    f,answer,tmp    : numbertype;
10    n,t        : longint;
11 procedure init; inline;
12 var
13    i,j : longint;
14    ch  : char;
15 begin
16    readln(n,t);
17    for i:=1 to n do
18    begin
19       for j:=1 to n do
20       begin
21      read(ch);
22      map[i,j]:=ord(ch)-48;
23       end;
24       readln;
25    end;
26    fillchar(f,sizeof(f),0);
27    for i:=1 to n do
28       for j:=1 to 8 do
29      f[9*(i-1)+j,9*(i-1)+j+1]:=1;
30    for i:=1 to n do
31       for j:=1 to n do
32      if map[i,j]>0 then
33         f[9*(i-1)+map[i,j],9*(j-1)+1]:=1;
34 end; { init }
35 procedure main(y:longint ); inline;
36 var
37    i,tt,j,k,l,s    : longint;
38 begin
39    for i:=1 to 9*n do
40       for j:=1 to 9*n do
41      power[1][i,j]:=f[i,j];
42    s:=y;
43    tt:=trunc(ln(y)/ln(2))+1;
44    fillchar(v,sizeof(v),false);
45    dec(s);
46    answer:=f;
47    for i:=1 to tt do
48       if (s>>(i-1))and 1=1 then
49      v[i]:=true;
50    for i:=2 to tt do
51    begin
52       fillchar(power[i],sizeof(power[i]),0);
53       for j:=1 to 9*n do
54      for k:=1 to 9*n do
55         for l:=1 to 9*n do
56            power[i][j,l]:=(power[i][j,l]+power[i-1][j,k]*power[i-1][k,l])mod 
57 
58 2009;
59    end;
60    for i:=1 to tt do
61       if v[i] then
62       begin
63      fillchar(tmp,sizeof(tmp),0);
64      for j:=1 to 9*n do
65         for k:=1 to 9*n do
66            for l:=1 to 9*n do
67           tmp[j,l]:=(tmp[j,l]+answer[j,k]*power[i][k,l])mod 2009;
68      for j:=1 to 9*n do
69         for k:=1 to 9*n do
70            answer[j,k]:=tmp[j,k];
71       end;
72 end; { main }
73 begin
74    assign(input,'road.in');reset(input);
75    assign(output,'road.out');rewrite(output);
76    init;
77    main(t);
78    writeln(answer[1,9*(n-1)+1]);
79    close(input);
80    close(output);
81 end.
posted @ 2012-04-17 18:07  Codinginging  阅读(458)  评论(0编辑  收藏  举报