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.