题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=1875

题解

如果没有这个“不能立刻沿着刚刚走来的路走回”,那么这个题就是一个常规的矩阵乘法。

考虑一下这个限制怎么解决。因为限制的是边,我们不妨考虑和边有关的矩阵。

首先把一条无向边拆成两个有向边,如果边 \(A\) 的终点和边 \(B\) 的起点相同,那么我们就说从边 \(A\) 通向边 \(B\)。但是,同源的有向边(也就是从同一条无向边拆成的两条有向边)之间不能建边。

但是为了能够区分出来从 \(S\) 到 \(T\) 的路径,我们建立两个虚点,从 \(SS\) 到 \(S\) 的一条边和从 \(T\) 到 \(TT\) 的边。

然后我们把这个东西跑一边矩阵快速幂即可。


时间复杂度 \(O(m^3\log n)\)。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 120 + 4;
const int P = 45989; int n, m, T, st, ed;
char s[N]; struct Edge { int to, ne; } g[N << 1]; int head[N], tot = 1;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); } inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, const int &y) { x += y; x >= P ? x -= P : x; }
inline int fpow(int x, int y) {
int ans = 1;
for (; y; y >>= 1, x = x * x % P) if (y & 1) ans = ans * x % P;
return ans;
} struct Matrix {
int a[N][N]; inline Matrix() { memset(a, 0, sizeof(a)); }
inline Matrix(const int &x) {
memset(a, 0, sizeof(a));
for (int i = 1; i <= m; ++i) a[i][i] = x;
} inline Matrix operator * (const Matrix &b) {
Matrix c;
for (int k = 1; k <= m; ++k)
for (int i = 1; i <= m; ++i)
for (int j = 1; j <= m; ++j)
sadd(c.a[i][j], a[i][k] * b.a[k][j] % P);
return c;
}
} A; inline Matrix fpow(Matrix x, int y) {
Matrix ans(1);
for (; y; y >>= 1, x = x * x) if (y & 1) ans = ans * x;
return ans;
}
inline void work() {
addedge(++n, st), addedge(ed, ++n), m = tot;
for (int x = 0; x <= n; ++x)
for fec(i, x, y) for fec(j, y, z) if ((i ^ j) != 1) A.a[i][j] = 1;
A = fpow(A, T + 1);
printf("%d\n", A.a[m - 1][m]);
} inline void init() {
read(n), read(m), read(T), read(st), read(ed);
int x, y;
for (int i = 1; i <= m; ++i) read(x), read(y), adde(x, y);
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj1875 [SDOI2009]HH去散步 矩阵快速幂的更多相关文章

  1. bzoj1875 [SDOI2009]HH去散步——矩阵快速幂

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1875 有个限制是不能走回头路,比较麻烦: 所以把矩阵中的元素设成边的经过次数,单向边之间就好 ...

  2. 【BZOJ】1875: [SDOI2009]HH去散步 矩阵快速幂

    [题意]给定n个点m边的无向图,求A到B恰好经过t条边的路径数,路径须满足每条边都和前一条边不同.n<=20,m<=60,t<=2^30. [算法]矩阵快速幂 [题解]将图的邻接矩阵 ...

  3. 【bzoj1875】【JZYZOJ1354】[SDOI2009]HH去散步 矩阵快速幂 点边转换

    http://172.20.6.3/Problem_Show.asp?id=1354 http://www.lydsy.com/JudgeOnline/problem.php?id=1875  题意: ...

  4. [luogu2151 SDOI2009] HH去散步 (矩阵快速幂)

    传送门 题目描述 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH ...

  5. BZOJ1875 [SDOI2009]HH去散步 矩阵

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1875 题意概括 在一个无向图(有重边无自环)中走,不能在经过连续经过某一条边2次. 现在走t步,问 ...

  6. BZOJ 1875 HH去散步(矩阵快速幂)

    题意: 给定一张无向图,每条路的长度都是1,没有自环,可能有重边,给定起点与终点,求从起点走t步到达终点的方案数. 每一步走的时候要求不能走上一条刚刚走的路. 解析: 显然需要搞出个矩阵之后矩乘. 然 ...

  7. bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法

    1875: [SDOI2009]HH去散步 Time Limit: 20 Sec  Memory Limit: 64 MB Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走, ...

  8. bzoj1875: [SDOI2009]HH去散步

    终于A了...早上按自己以前的写法一直WA.下午换了一种写法就A了qwq #include<cstdio> #include<cstring> #include<iost ...

  9. [bzoj1875][SDOI2009] HH去散步 [dp+矩阵快速幂]

    题面 传送门 正文 其实就是让你求有多少条长度为t的路径,但是有一个特殊条件:不能走过一条边以后又立刻反着走一次(如果两次经过同意条边中间隔了别的边是可以的) 如果没有这个特殊条件,我们很容易想到dp ...

随机推荐

  1. LinkedBlockingQueue 源码分析

    LinkedBlockingQueue LinkedBlockingQueue 是基于链表实现的,可以选择有界或无界的阻塞队列. 队列的元素按照 FIFO 的顺序访问,新增元素添加到队列尾部,移除元素 ...

  2. PHP会话

    B/S请求响应模式是无状态的.任意的请求间不存在任何的联系,不能将请求状态保持下去. 会话技术可以给每个浏览器分配持久数据,这些数据不会随着一次请求和相应结束而销毁. COOKIE cookie是一种 ...

  3. 07 oracle 归档模式 inactive/current redo log损坏修复--以及错误ORA-00600: internal error code, arguments: [2663], [0], [9710724], [0], [9711142], [], [], [], [], [], [], []

    07 oracle 归档模式 inactive/current redo log损坏修复--以及错误ORA-00600: internal error code, arguments: [2663], ...

  4. .net refactor 命令行

    VS中设置项目的编译后事件命令(此命令会在程序集生成后自动在原位置加密,覆盖原来的程序集): "C:\Program Files (x86)\Eziriz\.NET Reactor\dotN ...

  5. 转:高效实用的.NET开源项目

    本文转自:http://www.cnblogs.com/pengze0902/p/7669631.html 似乎...很久很久没有写博客了,一直都想写两篇,但是却没有时间写.感觉最近有很多事情需要处理 ...

  6. nvm-windows编译源码 go遇到的问题

    异常: Microsoft Windows [Version 10.0.17134.1006] (c) Microsoft Corporation. All rights reserved. C:\U ...

  7. 编译的时候出现"/usr/bin/ld: cannot find -lz

    编译的时候出现"/usr/bin/ld: cannot find -lz"错误,需要安装zlib-dev这个包,在线安装命令为:apt-get install zlib1g-dev ...

  8. 20190905 Lombok常用注解

    Lombok常用注解 val 用于声明类型,将从初始化表达式推断出类型,仅适用于局部变量和foreach循环,而不适用于字段.声明的局部变量为final变量. Java自带类型推断随着JDK版本提升越 ...

  9. 20190902 On Java8 第十六章 代码校验

    第十六章 代码校验 你永远不能保证你的代码是正确的,你只能证明它是错的. 测试 测试覆盖率的幻觉 测试覆盖率,同样也称为代码覆盖率,度量代码的测试百分比.百分比越高,测试的覆盖率越大. 当分析一个未知 ...

  10. 多线程09-Mutex

        )))                 {                     Console.WriteLine("second instance is runing" ...