bzoj4773 负环 倍增+矩阵
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=4773
题解
最小的负环的长度,等价于最小的 \(len\) 使得存在一条从点 \(i\) 到自己存在一条长度 \(\leq len\) 的负权路径。
为了把 \(\leq len\) 转化为 \(=len\),我们可以给每一个点建立有个边权为 \(0\) 的自环。
所以考虑倍增邻接矩阵,维护两点之间的经过 \(2^i\) 条边的最短路。
倍增的时候判断走了那么多步有没有负环就可以了。
最后结束的时候再判断一次,防止无解。
时间复杂度 \(O(n^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 = 300 + 7;
const int INF = 0x3f3f3f3f;
int n, m;
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, B[9];
inline void work() {
B[0] = A, A = Matrix(0);
for (int i = 1; i < 9; ++i) B[i] = B[i - 1] * B[i - 1];
int ans = 0;
for (int i = 8; ~i; --i) {
Matrix C = A * B[i];
int mn = INF;
for (int j = 1; j <= n; ++j) smin(mn, C.a[j][j]);
if (mn >= 0) A = C, ans += 1 << i;
}
A = A * B[0];
int mn = INF;
for (int j = 1; j <= n; ++j) smin(mn, A.a[j][j]);
if (mn >= 0) puts("0");
else printf("%d\n", ans + 1);
}
inline void init() {
read(n), read(m);
int x, y, z;
A = Matrix(0);
for (int i = 1; i <= m; ++i) read(x), read(y), read(z), A.a[x][y] = z;
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
bzoj4773 负环 倍增+矩阵的更多相关文章
- 4.28 省选模拟赛 负环 倍增 矩阵乘法 dp
容易想到 这个环一定是简单环. 考虑如果是复杂环 那么显然对于其中的第一个简单环来说 要么其权值为负 如果为正没必要走一圈 走一部分即可. 对于前者 显然可以找到更小的 对于第二部分是递归定义的. 综 ...
- BZOJ4773: 负环(倍增Floyd)
题意 题目链接 Sol 倍增Floyd,妙妙喵 一个很显然的思路(然而我想不到是用\(f[k][i][j]\)表示从\(i\)号点出发,走\(k\)步到\(j\)的最小值 但是这样复杂度是\(O(n^ ...
- 【BZOJ4773】负环 倍增Floyd
[BZOJ4773]负环 Description 在忘记考虑负环之后,黎瑟的算法又出错了.对于边带权的有向图 G = (V, E),请找出一个点数最小的环,使得 环上的边权和为负数.保证图中不包含重边 ...
- bzoj4773: 负环(倍增floyd)
浴谷夏令营例题...讲师讲的很清楚,没看题解代码就自己敲出来了 f[l][i][j]表示i到j走2^l条边的最短距离,显然有f[l][i][j]=min(f[l][i][j],f[l-1][i][k] ...
- bzoj 4773: 负环——倍增
Description 在忘记考虑负环之后,黎瑟的算法又出错了.对于边带权的有向图 G = (V, E),请找出一个点数最小的环,使得 环上的边权和为负数.保证图中不包含重边和自环. Input 第1 ...
- 2018.11.09 bzoj4773: 负环(倍增+floyd)
传送门 跟上一道题差不多. 考虑如果环上点的个数跟最短路长度有单调性那么可以直接上倍增+floyd. 然而并没有什么单调性. 于是我们最开始给每个点初始化一个长度为0的自环,于是就有单调性了. 代码: ...
- BZOJ4773 负环(floyd+倍增)
倍增floyd求出经过<=2k条边时两点间最短路,一个点到自身的最短路就是包含该点的最小环.然后倍增找答案即可.注意初始时到自身的最短路设为0,这样求出的最短路就是经过<=2k条边的而不是 ...
- bzoj4773: 负环
题解: 网上还有一种spfa+深度限制的算法 https://www.cnblogs.com/BearChild/p/6624302.html 是不加队列优化的spfa,我觉得复杂度上限是bellma ...
- BZOJ 4773: 负环 倍增Floyd
现在看来这道题就非常好理解了. 可以将问题转化为求两点间经过 $k$ 个点的路径最小值,然后枚举剩余的那一个点即可. #include <cstdio> #include <cstr ...
随机推荐
- 【洛谷P1443 马的遍历】
题目链接(%%%jyy大佬) 题目描述 有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步 输入输出格式 输入格式: 一行四个数 ...
- int 和 字节 相互转换
In [10]: n = 0xf1f2 In [11]: bin(n) Out[11]: '0b1111000111110010' In [12]: n.bit_length() Out[12]: 1 ...
- z-index的各种坑
z-index属性 z-index : auto | number z-index 属性设置元素的堆叠顺序,如果为正数,则离用户更近,为负数则表示离用户更远: 拥有更高堆叠顺序的元素总是会处于堆叠顺序 ...
- 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_6_字节输出流写多个字节的方法
一次写多个字节的方法 要在txt内显示100.49代表1 48 代表0 一次写多个字节 负数前两个组成一个中文.-65和-66 字节数组的一部分 写入字符串方法 当前用的编码格式是utf-8,utf- ...
- C++ 命名管道示例
想做一个 Hook CreateFile 重定向到内存的功能,貌似可以假借命名管道实现这个功能.不熟悉命名管道,做了几个demo,如下: Server: // NamedPipeServer.cpp ...
- python 递归,深度优先搜索与广度优先搜索算法模拟实现
一.递归原理小案例分析 (1)# 概述 递归:即一个函数调用了自身,即实现了递归 凡是循环能做到的事,递归一般都能做到! (2)# 写递归的过程 1.写出临界条件 2.找出这一次和上一次关系 3.假设 ...
- Android安全测试(三)应用完整性检验检测
二.app应用完整性1.测试环境 SDK: Java JDK, Android SDK. 工具: 7zip,apktool.jar,signapk.jar 2.操作步骤 第一步:把需要检测的apk放置 ...
- package__init__用途
baidu包,假设在baidu包下有N个模块,分别是baidu1.py.baidu2.py,baidu3.py, baiduHq.py(baidu1.py,baidu2.py,baidu3.py模块代 ...
- Java设计模式——建造者模式(创建型模式)
概述 建造者模式也称为生成器模式,是一种对象创建型模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象. 建造者模式意在为重叠构造 ...
- exsi中使用vSphere客户端复制克隆虚拟机
免费的VMWare ESXi5.5非常强大,使用ESXi经常会遇到这样的问题,我需要建立多个虚拟机,系统一个一个安装很麻烦.VMware ESXi.VMware vCenter Server 和 vS ...