题目传送门

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

题解

换个方法定义矩阵乘法:先加再取 \(\min\)。

对于一个 \(n\times m\) 的矩阵 \(A\),和一个 \(m\times l\) 的矩阵 \(B\) 它们的乘积 \(C\) 是一个 \(n \times l\) 的矩阵。

\[C_{i, j} = \min_{k=1}^m A_{i, k}+B_{k,j}
\]


关于这个东西的结合律的证明和一般的矩阵乘法类似,直接带入就可以了。大家可以看一下我的另一篇博客。动态 DP 学习笔记 里面有提到。

然后显然就是先建出来邻接矩阵,然后求它的 \(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 = 200 + 7; int T, n, m, st, ed;
int b[N]; struct Edges { int u, v, w; } a[N]; struct Matrix {
int a[N][N]; inline Matrix() { memset(a, 0x3f, sizeof(a)); }
inline Matrix(const int &x) {
memset(a, 0x3f, sizeof(a));
for (int i = 1; i <= n; ++i) a[i][i] = x;
} inline Matrix operator * (const Matrix &b) {
Matrix c;
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
smin(c.a[i][j], a[i][k] + b.a[k][j]);
return c;
}
} A; inline Matrix fpow(Matrix x, int y) {
Matrix ans(0);
for (; y; y >>= 1, x = x * x) if (y & 1) ans = ans * x;
return ans;
} inline void work() {
std::sort(b + 1, b + (m << 1) + 1);
n = std::unique(b + 1, b + (m << 1) + 1) - b - 1;
for (int i = 1; i <= m; ++i) {
int x = a[i].u, y = a[i].v, z = a[i].w;
x = std::lower_bound(b + 1, b + n + 1, x) - b;
y = std::lower_bound(b + 1, b + n + 1, y) - b;
A.a[x][y] = A.a[y][x] = z;
} printf("%d\n", fpow(A, T).a[std::lower_bound(b + 1, b + n + 1, st) - b][std::lower_bound(b + 1, b + n + 1, ed) - b]);
} inline void init() {
read(T), read(m), read(st), read(ed);
for (int i = 1; i <= m; ++i)
read(a[i].w), read(a[i].u), read(a[i].v),
b[(i << 1) - 1] = a[i].u, b[i << 1] = a[i].v;
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj1706 [usaco2007 Nov]relays 奶牛接力跑 矩阵快速幂的更多相关文章

  1. 【BZOJ1706】[usaco2007 Nov]relays 奶牛接力跑 矩阵乘法

    [BZOJ1706][usaco2007 Nov]relays 奶牛接力跑 Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项 ...

  2. bzoj1706: [Usaco2007 Nov]relays 奶牛接力跑 (Floyd+新姿势)

    题目大意:有t(t<=100)条无向边连接两点,求s到e刚好经过n(n<=10^7)条路径的最小距离. 第一反应分层图,但是一看n就懵逼了,不会写.看了题解之后才知道可以这么玩... 首先 ...

  3. [bzoj1706] [usaco2007 Nov]relays 奶牛接力跑

    大概是叫倍增Floyd? 显然最多200个点...f[i][j][k]表示从j到k,走2^i步的最小路程.就随便转移了.. 查询的话就是把n二进制位上是1的那些都并起来. #include<cs ...

  4. BZOJ_[usaco2007 Nov]relays 奶牛接力跑_离散化+倍增弗洛伊德

    BZOJ_[usaco2007 Nov]relays 奶牛接力跑_离散化+倍增弗洛伊德 Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们 ...

  5. bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑【矩阵乘法+Floyd】

    唔不知道怎么说--大概核心是把矩阵快速幂的乘法部分变成了Floyd一样的东西,非常之神 首先把点离散一下,最多有200个,然后建立邻接矩阵,a[u][v]为(u,v)之间的距离,没路就是inf 然后注 ...

  6. 【BZOJ】1706: [usaco2007 Nov]relays 奶牛接力跑

    [题意]给定m条边的无向图,起点s,终点t,要求找出s到t恰好经过n条边的最短路径.n<=10^6,m<=100. [算法]floyd+矩阵快速幂 [题解] 先对点离散化,得到点数N. 对 ...

  7. zjoj1706: [usaco2007 Nov]relays 奶牛接力跑

    矩阵乘法(快速幂) 为说明方便,这里让\(k\)为点数,\(n\)为路径长度. 先将点都离散化,这样最后的点只有\(2k\)个. 先考虑一种暴力,每次用\(O(k^3)\)的复杂度来暴力更新,设当前长 ...

  8. 【bzoj1706】[usaco2007 Nov]relays 奶牛接力跑 离散化+倍增Floyd

    题目描述 FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力跑的地点 自然是在牧场中现有的T(2 <= T <= 100) ...

  9. bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑——倍增floyd

    Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力跑的地点 自然是在牧场中现有的T(2 <= T < ...

随机推荐

  1. 前端进阶系列(二):css常见布局解决方案

    水平居中布局 margin+定宽 <div class="parent"> <div class="child">Demo</di ...

  2. 认识了一个新的手机游戏剖析工具- SnapDragon Profiler

    原来这个是高通的工具,具说UNITY官方推荐了这个工具.大概看了下,可以从宏观上实时剖析手机应用的方方面面

  3. Linux驱动开发1——基础知识

    1.三类驱动 字符设备驱动:字节流,/dev下有设备节点,file_operations,inode, file 块设备驱动:数据块,/dev下有设备节点,通常有文件系统 网络设备驱动:网络报文的收发 ...

  4. 如何在sql server数据库中建立主从表

    建立关联是通过外键引用实现的 例如建立一个学生表和班级表的关联,可以如下: create table class ( classid char(4) primary key not null, cla ...

  5. .net任务调度平台 Dyd.BaseService.TaskManager

    国外网速慢,最新版本迁移至http://git.oschina.net/chejiangyi/Dyd.BaseService.TaskManager .net 简单任务调度平台 用于.net dll, ...

  6. 观察者模式(jdk实现)

    1.定义 在对象中定义一对多的依赖,当一个对象改变状态,依赖它的对象会收到通知并更新. 2.实现   (主要通过jdk自己定义的观察者实现) 以气象站通知展示板为例子,当气象站收到的各种参数改变的时候 ...

  7. 【ABAP系列】SAP ABAP解析XML的示例程序

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP解析XML的示例 ...

  8. 管理MySQL 从入门到出门

    MySQL 中的数据库(Database)就像是一个容器,其中包含了各种对象.例如,数据表(Table).视图(View).存储过程(Stored Procedure)以及触发器(Trigger)等. ...

  9. C++学习笔记(七)--共用体、枚举、typedef

    1.共用体 union其定义与结构体类似:union 类型名{ 成员表列;};声明变量的方法也类似: a. union 类型名{            b. union { c.类型名 变量名; 成员 ...

  10. Redis介绍及入门安装及使用

    Redis介绍及入门安装及使用 什么是Redis Redis is an open source (BSD licensed), in-memory data structure store, use ...