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)条路径 ...
- spfa判断负环
会了spfa这么长时间竟然不会判断负环,今天刚回.. [例题]poj3259 题目大意:当农场主 John 在开垦他的农场时,他发现了许多奇怪的昆虫洞.这些昆虫洞是单向的,并且可以把你从入口送到出口, ...
- Wormholes---poj3259(最短路 spfa 判断负环 模板)
题目链接:http://poj.org/problem?id=3259 题意是问是否能通过虫洞回到过去: 虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts. 我们把虫洞看成是一条负权路,问 ...
- POJ 3259 Wormholes ( SPFA判断负环 && 思维 )
题意 : 给出 N 个点,以及 M 条双向路,每一条路的权值代表你在这条路上到达终点需要那么时间,接下来给出 W 个虫洞,虫洞给出的形式为 A B C 代表能将你从 A 送到 B 点,并且回到 C 个 ...
- Extended Traffic LightOJ - 1074 spfa判断负环
//判断负环 在负环内的城市输出? #include <iostream> #include <queue> #include <cstdio> #include ...
- Wormholes POJ - 3259 spfa判断负环
//判断负环 dist初始化为正无穷 //正环 负无穷 #include<iostream> #include<cstring> #include<queue> # ...
- UVA 558 SPFA 判断负环
这个承认自己没看懂题目,一开始以为题意是形成环路之后走一圈不会产生负值就输出,原来就是判断负环,用SPFA很好用,运用队列,在判断负环的时候,用一个数组专门保存某个点的访问次数,超过了N次即可断定有负 ...
- POJ3259 Wormholes(SPFA判断负环)
Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes ...
- L - The Shortest Path Gym - 101498L (dfs式spfa判断负环)
题目链接:https://cn.vjudge.net/contest/283066#problem/L 题目大意:T组测试样例,n个点,m条边,每一条边的信息是起点,终点,边权.问你是不是存在负环,如 ...
随机推荐
- shell 数值计算
shell中的赋值和操作默认都是字符串处理,在此记下shell中进行数学运算的几个特殊方法,以后用到的时候可以来看,呵呵. 1.错误方法举例 a) var=1+1 echo $var ...
- LeetCode——Nim Game
Description: You are playing the following Nim Game with your friend: There is a heap of stones on t ...
- Android studio 插件安装
安装插件步骤 一 CodeGlance 最大的用途:可用于快速定位代码.显示在右侧 二 Android Studio Prettify 可以将代码中的字符串写在string.xml文件中 选中字符串鼠 ...
- sencha touch list ListPaging使用详解
示例代码: Ext.define('app.view.message.List', { alternateClassName: 'messageList', extend: 'Ext.List', x ...
- HDU 2102 A计划(BFS/DFS走迷宫)
A计划 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- 利用Jenkins未授权获取服务器权限--Docker还来干扰--一次渗透的经历
Jenkins获取权限的过程 Jenkins存在未授权访问漏洞 Jenkins存在未授权访问漏洞,且项目具有读取权限,通过项目的日志获取到一个账号密码,尝试登录成功,打开控制台成功. 备注:控制台一般 ...
- 静态时序分析基础STA
静态时序分析SAT 1. 背景 静态时序分析的前提就是设计者先提出要求,然后时序分析工具才会根据特定的时序模型进行分析,给出正确是时序报告. 进行静态时序分析,主要目的就是为了提高系统工作主频 ...
- iOS property中的strong 、weak、copy 、assign 、retain 、unsafe_unretained 与autoreleasing区别和作用详解
iOS5中加入了新知识,就是ARC,其实我并不是很喜欢它,因为习惯了自己管理内存.但是学习还是很有必要的. 在iOS开发过程中,属性的定义往往与retain, assign, copy有关,我想大家都 ...
- iOS - 原生的CIFilter生成二维码和条形码
使用CIFilter可以不引入任何第三方库,就可以生成想要的二维码和条形码,今天简单的介绍一下使用CIFilter生成二维码和条形码.系统CIFilter生成的二维码和条形码的大小有时并不能满足需求, ...
- Git - 使用BitBucket和SourceTree进行源代码管理遇到POST git-receive-pack (chunked)
我使用的是SourceTree Mac版,提交到BitBucket时出现 一直处于 POST git-receive-pack (chunked) 状态,经过百度,解决问题 在使用SourceTre ...