spfa 判断负环 (转载)
当然,对于Spfa判负环,实际上还有优化:就是把判断单个点的入队次数大于n改为:如果总的点入队次数大于所有点两倍
时有负环,或者单个点的入队次数大于sqrt(点数)有负环。这样时间复杂度就降了很多了。
判断给定的有向图中是否存在负环。
利用 spfa 算法判断负环有两种方法:
1) spfa 的 dfs 形式,判断条件是存在一点在一条路径上出现多次。
2) spfa 的 bfs 形式,判断条件是存在一点入队次数大于总顶点数。
代码如下:
法 1 (spfa 的 dfs 形式):
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int oo = 1 << 30;
const int maxn = 1010;
struct Edge {
int u, v, t, next;
}edge[2010];
int prev[maxn], p[maxn], d[maxn];
bool vis[maxn], flag;
int tot;
void addEdge(int u, int v, int t) {
edge[tot].u = u;
edge[tot].v = v;
edge[tot].t = t;
edge[tot].next = prev[u];
prev[u] = tot ++;
}
void spfa(int u) {
int v;
for (int i = prev[u]; i != -1; i = edge[i].next) {
v = edge[i].v;
if (d[u] + edge[i].t < d[v]) {
if (vis[v]) { //存在一点在一条路径上出现多次
flag = true;
return ;
}
else {
d[v] = d[u] + edge[i].t;
vis[v] = true;
spfa(v);
}
}
}
}
int main() {
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int T;
int a, b, t;
int n, m;
scanf("%d", &T);
while (T --) {
scanf("%d%d", &n, &m);
memset(prev, -1, sizeof(prev));
tot = 0;
for (int i = 1; i <= m; i ++) {
scanf("%d%d%d", &a, &b, &t);
addEdge(a, b, t);
}
memset(vis, false, sizeof(vis));
fill(d, d + n, oo);
d[0] = 0;
flag = false;
spfa(0);
if (flag) printf("possible\n");
else printf("not possible\n");
}
return 0;
}
法 2 (spfa 的 bfs 形式):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int oo = 1 << 30;
const int maxn = 1010;
struct Edge {
int u, v, t, next;
}edge[2010];
int prev[maxn], p[maxn], d[maxn], in[maxn];
bool vis[maxn];
int tot;
queue<int> q;
void addEdge(int u, int v, int t) {
edge[tot].u = u;
edge[tot].v = v;
edge[tot].t = t;
edge[tot].next = prev[u];
prev[u] = tot ++;
}
bool spfa(int n) {
int u, v;
while (!q.empty()) q.pop();
memset(vis, false, sizeof(vis));
memset(in, 0, sizeof(in));
fill(d, d + n, oo);
d[0] = 0; vis[0] = true;
q.push(0);
while (!q.empty()) {
u = q.front();
vis[u] = false;
for (int i = prev[u]; i != -1; i = edge[i].next) {
v = edge[i].v;
if (d[u] + edge[i].t < d[v]) {
d[v] = d[u] + edge[i].t;
if (!vis[v]) {
in[v] ++;
if (in[v] > n) return true; //存在一点入队次数大于总顶点数
vis[v] = true;
q.push(v);
}
}
}
vis[u] = false;
q.pop();
}
return false;
}
int main() {
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int T;
int a, b, t;
int n, m;
scanf("%d", &T);
while (T --) {
scanf("%d%d", &n, &m);
memset(prev, -1, sizeof(prev));
tot = 0;
for (int i = 1; i <= m; i ++) {
scanf("%d%d%d", &a, &b, &t);
addEdge(a, b, t);
}
if (spfa(n)) printf("possible\n");
else printf("not possible\n");
}
return 0;
}
spfa 判断负环 (转载)相关推荐
- POJ 3259 Wormholes【最短路/SPFA判断负环模板】
农夫约翰在探索他的许多农场,发现了一些惊人的虫洞.虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径 ...
- UVA 558 SPFA 判断负环
这个承认自己没看懂题目,一开始以为题意是形成环路之后走一圈不会产生负值就输出,原来就是判断负环,用SPFA很好用,运用队列,在判断负环的时候,用一个数组专门保存某个点的访问次数,超过了N次即可断定有负 ...
- 负环——spfa判断负环的两种方式
第一种:(不推荐) 统计每个点的入队次数,如果某一个点入队了n次,则说明存在负环. 第二种: 统计当前每个点的最短路的边数,如果存在负环,负环上的某一个点的最短路边数一定会是正无穷,只要边数超过n(节 ...
- 算法基础课-搜索与图论-spfa-AcWing 852. spfa判断负环:spfa求负环板子
文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: dist[x] 表示从源点到x点的最短距离. spfa算法求最短路的算法步骤: 初始化一个队列,将起点入队. 取出队头元素t,遍历它 ...
- PKU3259-Wormholes(SPFA判断负环,含题意)
题目: 一开始被题目的梦幻给弄的晕乎乎.的却,作者很会yy. 意思是: 一个农夫有cas个田地,然后每个田地里面有nodeNum个结点,结点之间可能有多条路径(这是一个无向图),田地里还有w个虫洞(虫 ...
- spfa判断负环( 负环判定 + spfa )
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 impossible. 数据保证 ...
- AcWing 852. spfa判断负环(spfa or bellman)
题目链接 https://www.acwing.com/problem/content/description/854/ 思路 思路一 我们定义一个数组cnt,cnt[i]表示i这个点被更新的次数,那 ...
- 时光机 (spfa判断负环)
cnt数组记录每个点入栈次数,无负环时最大入栈次数为n,因为最短路最多有n-1条边. 有负环时最短路趋于负无穷,入栈次数大于n. #include<stdio.h> #include< ...
- Wormholes 虫洞 BZOJ 1715 spfa判断负环
John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地 ...
最新文章
- 利用 jquery 获取某个元素下的所有图片并改变其属性
- 为什么我喜欢Spring bean别名
- MC.9 与 LIS
- Codeforces Round #304 (Div. 2) D. Soldier and Number Game 数学 质因数个数
- 利用NLB建立双机负载均衡群集
- JAVA 使用Jacob调用windows的Sapi实现文本转语音文件
- 【clickhouse】Clickhouse 版本号历史
- this.scrollheight获取textarea的高度是0_53小米电子时钟/v1.0 介绍
- PowerBuilder制作纸牌游戏
- 【文献翻译】基于CVSS的IT系统网络安全风险定量评估方法-A Quantitative CVSS-Based Cyber Security Risk Assessment Methodology
- 940mx黑苹果驱动_黑苹果 Clover 驱动配置文件分享
- 鼠标经过变成小手/箭头
- 微信小程序调用地图和跟据经纬度打开手机地图导航
- 【Alpha】Scrum Meeting 5
- 清华大学百年校庆给清华大学的一封信
- 深度学习——Dual Regression Networks for Single Image Super-Resolution(DRN)
- trinity运行原理及常见报错(一)
- 以后看电影就按这个名单了
- new String[0]的作用
- 《一个人的朝圣》读书摘记
热门文章
- 最大功率28W,高通新一代快充技术QC4.0曝光
- 《为自己工作——世界顶级设计师成功法则》—第1章1.7节平衡
- 二叉查找树(二叉排序树)创建,插入,删除操作。
- 软件测试之三——路径覆盖
- Linux知识点记录
- nfs服务器安装与客户端安装
- 骁龙617 android7,骁龙617手机有哪些?骁龙617手机汇总
- phpstudy php日志,phpstudy开启网站Apache日志并且按照日期划分创建
- apache 提示You don't have permission to access /test.php on this server.怎样解决
- activeMQ安装9(window下)