[BZOJ 1297][SCOI2009]迷路
1297: [SCOI2009]迷路
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1418 Solved: 1017
[Submit][Status][Discuss]Description
windy在有向图中迷路了。 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。
Input
第一行包含两个整数,N T。 接下来有 N 行,每行一个长度为 N 的字符串。 第i行第j列为'0'表示从节点i到节点j没有边。 为'1'到'9'表示从节点i到节点j需要耗费的时间。
Output
包含一个整数,可能的路径数,这个数可能很大,只需输出这个数除以2009的余数。
Sample Input
【输入样例一】
2 2
11
00【输入样例二】
5 30
12045
07105
47805
12024
12345Sample Output
【输出样例一】
1【样例解释一】
0->0->1【输出样例二】
852HINT
30%的数据,满足 2 <= N <= 5 ; 1 <= T <= 30 。 100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000 。
一周之前做的了...想了想还是写写题解吧...
题解
首先我们都知道的一个结论是对于一个简单图 $G$ 的邻接矩阵 $M$ , $M^k_{i,j}$ 就是从点 $i$ 走 $k$ 条边到点 $j$ 的方案数.
然而这个结论只适用于两点间的边数, 而我们注意到本题中两点间的边是带权的, 我们就不能直接使用这个结论了
接着我们可以想到的其中一个解法是把一条边权为 $k$ 的边通过在其中插入虚拟结点的方式拆成 $k$ 条边, 但是极端情况下可能有 $100$ 条带权边要拆, 每条带权边可能会拆成 $10$ 条无权边, 其中会产生大量虚拟结点, 极端情况下总结点数会大于 $1000$ , 矩阵相应的也会变成这个数量级, 然后一次 $O(n^3)$ 的矩阵乘法都跑不完...╮(╯﹏╰)╭
继续思考优化方式, 现在的瓶颈在于虚拟结点过多, 我们可以思考如何缩减虚拟结点的数量. 我们可以尝试事先将一些虚拟结点和原结点连成链, 然后对于带权边都指向这条链上的对应位置, 将带权边前方的链合并起来(一股Trie的味道?)来最小化结点数量, 这样就可以把结点数量控制在 $100$ 的量级
然后就很棒棒了, 构造完矩阵无脑跑快速幂就好了(o゚▽゚)o
反正别像我一样打出了正解输出的时候把倍增矩阵当成答案矩阵输出就行了( ̄. ̄)
参考代码
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> const int MAXN=;
const int MOD=; int n,t;
char buf[MAXN];
int m[MAXN][MAXN];
int x[MAXN][MAXN];
int mt[MAXN][MAXN]; int Encode(int);
void Initialize();
int Encode(int,int); int main(){
Initialize();
// t--;
while(t>){
if((t&)!=){
memset(mt,,sizeof(mt));
for(int i=;i<n*;i++)
for(int j=;j<n*;j++)
for(int k=;k<n*;k++)
(mt[i][j]+=x[i][k]*m[k][j])%=MOD;
memcpy(x,mt,sizeof(mt));
}
memset(mt,,sizeof(mt));
for(int i=;i<n*;i++)
for(int j=;j<n*;j++)
for(int k=;k<n*;k++)
(mt[i][j]+=m[i][k]*m[k][j])%=MOD;
memcpy(m,mt,sizeof(mt));
t>>=;
}
printf("%d\n",x[][Encode(n-)]);
return ;
} void Initialize(){
scanf("%d%d",&n,&t);
for(int i=;i<n;i++){
for(int j=;j<=;j++){
m[Encode(i,j)][Encode(i,j-)]=;
}
}
for(int i=;i<n;i++){
scanf("%s",buf);
for(int j=;j<n;j++){
if(buf[j]!=''){
m[Encode(i)][Encode(j,buf[j]-'')]=;
}
}
}
for(int i=;i<n*;i++)
x[i][i]=;
} inline int Encode(int k,int len){
return k*+len-;
} inline int Encode(int k){
return k*;
}
Backup
[BZOJ 1297][SCOI2009]迷路的更多相关文章
- BZOJ 1297: [SCOI2009]迷路( dp + 矩阵快速幂 )
递推式很明显...但是要做矩阵乘法就得拆点..我一开始很脑残地对于每一条权值v>1的边都新建v-1个节点去转移...然后就TLE了...把每个点拆成9个就可以了...时间复杂度O((9N)^3* ...
- BZOJ 1297: [SCOI2009]迷路 [矩阵快速幂]
Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同 ...
- 1297: [SCOI2009]迷路
1297: [SCOI2009]迷路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 652 Solved: 442[Submit][Status] ...
- 【BZOJ】1297: [SCOI2009]迷路
[题意]给定n个点的有向带边权图,求0到n-1长度恰好为T的路径数.n<=10,T<=10^9,边权1<=wi<=9. [算法]矩阵快速幂 [题解]这道题的边权全部为1时,有简 ...
- 1297. [SCOI2009]迷路【矩阵乘法】
Description windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同 ...
- 【矩阵快速幂】bzoj1297 [SCOI2009]迷路
1297: [SCOI2009]迷路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1407 Solved: 1007[Submit][Status ...
- [Bzoj1297][Scoi2009 ]迷路 (矩阵乘法 + 拆点)
1297: [SCOI2009]迷路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1385 Solved: 993[Submit][Status] ...
- 【BZOJ1297】[SCOI2009]迷路(矩阵快速幂)
[BZOJ1297][SCOI2009]迷路(矩阵快速幂) 题面 BZOJ 洛谷 题解 因为边权最大为\(9\),所以记录往前记录\(9\)个单位时间前的.到达每个点的方案数就好了,那么矩阵大小就是\ ...
- B20J_1297_[SCOI2009]迷路_矩阵乘法
B20J_1297_[SCOI2009]迷路_矩阵乘法 题意:有向图 N 个节点,从节点 0 出发,必须恰好在 T 时刻到达节点 N-1.总共有多少种不同的路径? 2 <= N <= 10 ...
随机推荐
- Error creating bean with name 'com.you.user.dao.StudentDaoTest': Injection of autowired dependencies
1.错误描述 七月 13, 2014 6:37:41 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBean ...
- RHEL部署ipa红帽身份验证
1.先下载必须包 yum install -y ipa-server bind bind-dyndb-ldap 2.初始化ipa基本配置 ipa-server-install * Configure ...
- python基础练习题
购物车程序 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/3/6 21:01 # @Author : hyang # @Si ...
- 一个2D平面游戏,的碰撞引擎实现
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); i ...
- [SPOJ]DISUBSTR:Distinct Substrings&[SPOJ]SUBST1:New Distinct Substrings
题面 Vjudge Vjudge Sol 求一个串不同子串的个数 每个子串一定是某个后缀的前缀,也就是求所有后缀不同前缀的个数 每来一个后缀\(suf(i)\)就会有,\(len-sa[i]+1\)的 ...
- tar命令核心应用案列及多重参数和find组合应用
tar zcvf 压缩包 文件 打包:尽量切换到打包目录的上级目录,然后用相对路径打包 tar zcvf [随意路径] /框 [相对路径] 一堆苹果 tar tf 查看内容 -z --gzip -- ...
- 机器学习-kNN
基于Peter Harrington所著<Machine Learning in Action> kNN,即k-NearestNeighbor算法,是一种最简单的分类算法,拿这个当机器学习 ...
- VHDL和verilog应该先学哪个?
网上有太多的VHDL和verilog比较的文章,基本上说的都是VHDL和verilog之间可以实现同一级别的描述,包括仿真级.寄存器传输级.电路级,所以可以认为两者是等同级别的语言.很多时候会了其中一 ...
- Python 常用命令
对Python进行软件的安装.卸载和查看,是我们在日常工作中经常要做的事情,有的时候会突然忘记常用的命令,所以在此记录下来: pip 安装软件包 pip install xxx 卸载软件包 pip u ...
- char码值对应列表大全
Char("0") 为0的字符Char("1") Char("2") Char("3") Char("4&qu ...