BZOJ4386 [POI2015]Wycieczki 矩阵+倍增
时间:2019-09-09
本文章向大家介绍BZOJ4386 [POI2015]Wycieczki 矩阵+倍增,主要包括BZOJ4386 [POI2015]Wycieczki 矩阵+倍增使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=4386
题解
一眼就可以看出来是邻接矩阵快速幂。
可是这里的边权不为 \(1\)。不过可以发现,边权最多为 \(3\)。但是边的数量很多,不适合拆边,那就拆点吧。对于一条 \(x \to y\) 的边,就建立一个 \(x_0\to y_{w - 1}\) 的边,\(w\) 为边权。
然后就建立矩阵就可以了。因为我们需要统计第 \(i\) 步之前一共有多少路径,所以可以新建一个节点,每个点向这个点连一条有向边,这个点自己再来一个自环。
然后预处理 \(B_i\) 为走了 \(2^i\) 步的矩阵,直接倍增出来答案就可以了。
下面是代码,矩阵乘法的复杂度为 \(O(n^3)\),一共倍增 \(O(\log k)\) 次,因此总的时间复杂度为 \(O(n^3\log k)\)。
#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 = 40 * 3 + 7;
int n, m;
ll k;
struct Matrix {
ll a[N][N];
inline Matrix() { memset(a, 0, sizeof(a)); }
inline Matrix operator * (const Matrix &b) {
Matrix c;
for (int k = 0; k <= n; ++k)
for (int i = 0; i <= n; ++i)
for (int j = 0; j <= n; ++j)
c.a[i][j] += a[i][k] * b.a[k][j];
return c;
}
inline void print() const {
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= n; ++j) dbg("%lld ", a[i][j]);
dbg("\n");
}
}
} A, B[N];
inline bool isfull(const Matrix &a) {
ll cnt = 0;
for (int i = 1; i <= n / 3; ++i) {
cnt += a.a[i][0] - 1;
if (cnt >= k) return 1;
}
return 0;
}
inline void work() {
n = n * 3, B[0] = A;
int lim = 0;
for (int i = 1; i <= 70; ++i) {
B[i] = B[i - 1] * B[i - 1];
++lim;
if (isfull(B[i])) break;
}
if (!isfull(B[lim--])) {
puts("-1");
return;
}
memset(A.a, 0, sizeof(A.a));
for (int i = 0; i <= n; ++i) A.a[i][i] = 1;
ll ans = 0;
for (int i = lim; ~i; --i) {
const Matrix &tmp = A * B[i];
if (!isfull(tmp)) A = tmp, ans += 1ll << i;
}
printf("%lld\n", ans);
}
inline void init() {
read(n), read(m), read(k);
for (int i = 1; i <= m; ++i) {
int x, y, z;
read(x), read(y), read(z);
if (z == 1) ++A.a[x][y];
if (z == 2) ++A.a[x][y + n];
if (z == 3) ++A.a[x][y + n * 2];
}
for (int i = 1; i <= n; ++i) A.a[i][0] = A.a[i + n][i] = A.a[i + n * 2][i + n] = 1;
A.a[0][0] = 1;
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
原文地址:https://www.cnblogs.com/hankeke/p/BZOJ4386.html
- JS魔法堂:关于元素位置和鼠标位置的属性
- MyBatis魔法堂:Insert操作详解(返回主键、批量插入)
- Winodws安装系统时,通过安装磁盘进行分区
- Eclipse安装SVN插件
- JS魔法堂:IE5~9的Drag&Drop API
- mysql 5.7版本目录无data文件夹的解决办法
- 【UML】——为什么要使用UML
- hql中setDate和setTimeStamp的区别
- Spring源码解析——如何阅读源码
- java获取当前时间和前一天日期
- 国内首个二代基因测序 FPGA 加速方案-背后的技术
- Java基础04 封装与接口
- Maven那点事儿(Eclipse版)
- 【Spring开发】—— Spring注入静态变量
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux在丢失的情况下重置密码的教程
- Linux内核宏container_of的深度剖析
- CentOS 7.3配置Nginx虚拟主机的方法步骤
- Linux下alias命令的用法详解
- Linux搭建自己Nexus私服的实现方法
- centos7系统nginx服务器下phalcon环境搭建方法详解
- Logrotate实现Catalina.out日志每俩小时切割示例
- Linux常见问题解决方案汇总
- Linux中文件/文件夹无法删除的解决方案
- GNU Parallel的具体使用
- crontab定时任务不执行的原因分析与解决方法
- 在Linux中安装ASPNET.Core3.0运行时的示例代码
- linux Bash脚本判别使用者的身份方法示例
- 配置Linux使用LDAP用户认证的方法
- linux Dig命令使用大全