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条边,每一条边的信息是起点,终点,边权.问你是不是存在负环,如 ...
随机推荐
- Find–atime –ctime –mtime的用法与区别总结
转自 周五有同事问起find命令中-mtime n.-mtime –n以及-mtime +n的用法区别,当时虽然记得这里n是n个24个小时的意思,也是对所有这几个属性详细的用法却一知半解,索性周末仔细 ...
- margin-left:10px; 不同浏览器距离为什么不一样?
这是一个ie的bug.. 如果你设置margin对象是浮动的.ie就会把你设置的值双倍处理..可以设置浮动对象的 display:inline 解决
- php guzzle post async
use GuzzleHttp\Pool;use GuzzleHttp\Client;//use GuzzleHttp\Psr7\Request;use Psr\Http\Message\Respons ...
- 面试题:应用中很多jar包,比如spring、mybatis、redis等等,各自用的日志系统各异,怎么用slf4j统一输出?(上)
一.问题概述 如题所说,后端应用(非spring boot项目)通常用到了很多jar包,比如spring系列.mybatis.hibernate.各类连接数据库的客户端的jar包.可能这个jar包用的 ...
- laravel with 渴求式加载指定字段
在使用 Laravel 的关联查询中,我们经常使用 with 方法来避免 N+1 查询,但是 with 会将目标关联的所有字段全部查询出来,对于有强迫症的我们来说,当然是不允许的. 这时候我们可以使用 ...
- Mac下门罗币矿工样本分析
背景 今天遇到一个JSONRPC的告警,怀疑挖矿木马,IOC是132.148.245.101,无其他信息,随即google一波. 查询网络 遇到了,主动下载样本分析,下载地址:http://rjj.q ...
- 【读书笔记】setsockopt
setsockopt 设置套接口的选项. #include <sys/types.h> #include <sys/socket.h> int setsockopt(int ...
- Rails 添加新的运行环境
Rails自带了development.test和production三个environments 我们可以添加Staging database.yml staging: adapter: mysql ...
- github使用密钥登录
注册github之后 初次使用git的用户要使用git协议大概需要三个步骤: 一.生成密钥对 二.设置远程仓库(本文以github为例)上的公钥 一.生成密钥对 再window系统中可以通过x ...
- Linux--抓取Appium网站命令
# 获取各命令url地址 curl http://appium.io/docs/en/commands/device/app/is-app-installed/ 2>/dev/null | gr ...