首页 > 代码库 > bzoj1297: [SCOI2009]迷路(矩阵乘法+拆点)
bzoj1297: [SCOI2009]迷路(矩阵乘法+拆点)
题目大意:有向图里10个点,点与点之间距离不超过9,问从1刚好走过T距离到达n的方案数。
当时看到这题就想到了某道奶牛题(戳我)。这两道题的区别就是奶牛题问的是走T条边,这道题是每条边都有一个边权求走过T边权的方案数。。。所以可以看成奶牛题相当于这一题里的边权为1的情况。
首先边权为1就把奶牛题的floyd那段改成矩乘就可以了,那么接下来考虑边权不为1的情况,因为边权最多为9,我们就可以把每个点拆成9个点,x[1]~x[9]为x拆完的点,x[i]和x[i+1]连一条边权为1的边,然后x到y有一条边权为z的边,那么就把x的第z个点往y的第1个点连一条边,当然也可以把x[i]和x[i-1]连边然后把x的第一个点往y的第z个点连边,都是等价的,因为x跑到y第z个点再跑回y和x跑z个点再到y所走过的都是z个点。然后跑矩乘就可以辣。
代码如下:
type map=array[0..233,0..233]of longint; var n,m,t,i,j,x:longint; ch:char; mapp,a:map; function pos(i,j:longint):longint; begin exit((j-1)*m+i); end; procedure merge(var x,y:map); var i,j,k:longint; z:map; begin fillchar(z,sizeof(z),0); for i:=1 to n do for j:=1 to n do for k:=1 to n do z[i,j]:=(z[i,j]+x[i,k]*y[k,j])mod 2009; x:=z; end; procedure qp(y:longint); var x:map; begin x:=mapp; while y>0 do begin if y and 1=1 then merge(a,x); merge(x,x); y:=y>>1; end; end; begin readln(m,t); n:=m*9; for i:=1 to m do for j:=1 to 8 do mapp[pos(i,j),pos(i,j+1)]:=1; for i:=1 to m do begin for j:=1 to m do begin read(ch);x:=ord(ch)-ord(‘0‘); if x=0 then continue; mapp[pos(i,x),j]:=1; end; readln; end; for i:=1 to n do a[i,i]:=1; qp(t); writeln(a[1,m]); end.
bzoj1297: [SCOI2009]迷路(矩阵乘法+拆点)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。