题意:John的农场里field块地,path条路连接两块地,hole个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。我们的任务是知道会不会在从某块地出发后又回来,看到了离开之前的自己。

思路:

这题就是判断存不存在负环回路。

前M条是双向边,后面的W是单向的负边。

为了防止出现不连通,增加一个结点作为起点。起点到所有点的长度为0

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
/*
* 单源最短路bellman_ford算法,复杂度O(VE)
* 可以处理负边权图。
* 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路
* vector<Edge>E;先E.clear()初始化,然后加入所有边
* 点的编号从1开始
*/
const int INF = 0x3f3f3f3f;
const int MAXN = 550;
int dist[MAXN];
struct Edge
{int u, v;int cost;Edge(int _u = 0, int _v = 0, int _cost = 0) :u(_u), v(_v), cost(_cost){}
};
vector<Edge> E;
bool bellman_ford(int start, int n)//点的编号从1开始
{for (int i = 1; i <= n; i++)dist[i] = INF;dist[start] = 0;for (int i = 1; i<n; i++)//最多做n-1次{bool flag = false;for (int j = 0; j<E.size(); j++){int u = E[j].u;int v = E[j].v;int cost = E[j].cost;if (dist[v]>dist[u] + cost){dist[v] = dist[u] + cost;flag = true;}}if (!flag)return true;//没有负环回路}for (int j = 0; j<E.size(); j++)if (dist[E[j].v]>dist[E[j].u] + E[j].cost)return false;//第n次更新则有负环回路return true;//没有负环回路
}int main()
{int T;int N, M, W;int a, b, c;scanf("%d", &T);while (T--){scanf("%d%d%d", &N, &M, &W);E.clear();while (M--){scanf("%d%d%d", &a, &b, &c);E.push_back(Edge(a, b, c));E.push_back(Edge(b, a, c));}while (W--){scanf("%d%d%d", &a, &b, &c);E.push_back(Edge(a, b, -c));}for (int i = 1; i <= N; i++)E.push_back(Edge(N + 1, i, 0));if (!bellman_ford(N + 1, N + 1))printf("YES\n");else printf("NO\n");}return 0;
}

(2) 如果一开始对所有顶点i,都把dist[i]初始化为0,那么可以检查出所有的负圈

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
/*
* 单源最短路bellman_ford算法,复杂度O(VE)
* 可以处理负边权图。
* vector<Edge>E;先E.clear()初始化,然后加入所有边
* 点的编号从1开始
*/
const int INF = 0x3f3f3f3f;
const int MAXN = 550;
int dist[MAXN];
struct Edge
{int u, v;int cost;Edge(int _u = 0, int _v = 0, int _cost = 0) :u(_u), v(_v), cost(_cost){}
};
vector<Edge> E;
bool bellman_ford(int n)//点的编号从1开始
{for (int i = 1; i <= n; i++)dist[i] = 0;for (int i = 1; i<n; i++)//最多做n-1次{bool flag = false;for (int j = 0; j<E.size(); j++){int u = E[j].u;int v = E[j].v;int cost = E[j].cost;if (dist[v]>dist[u] + cost){dist[v] = dist[u] + cost;flag = true;}}if (!flag)return true;//没有负环回路}for (int j = 0; j<E.size(); j++)if (dist[E[j].v]>dist[E[j].u] + E[j].cost)return false;//第n次更新则有负环回路return true;//没有负环回路
}int main()
{int T;int N, M, W;int a, b, c;scanf("%d", &T);while (T--){scanf("%d%d%d", &N, &M, &W);E.clear();while (M--){scanf("%d%d%d", &a, &b, &c);E.push_back(Edge(a, b, c));E.push_back(Edge(b, a, c));}while (W--){scanf("%d%d%d", &a, &b, &c);E.push_back(Edge(a, b, -c));}if (!bellman_ford(N))printf("YES\n");else printf("NO\n");}return 0;
}

(3) SPFA

某个顶点进入队列的次数超过N,则有负环

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
/*
* 单源最短路SPFA
*/
const int MAXN = 1010;
const int INF = 0x3f3f3f3f;
struct Edge
{int v;int cost;Edge(int _v = 0, int _cost = 0) :v(_v), cost(_cost){}
};vector<Edge> E[MAXN];void addedge(int u, int v, int w)
{E[u].push_back(Edge(v, w));
}bool vis[MAXN];
int cnt[MAXN];
int dist[MAXN];bool SPFA(int start, int n)
{memset(vis, false, sizeof(vis));for (int i = 1; i <= n; i++)dist[i] = INF;dist[start] = 0;vis[start] = true;queue<int>que;while (!que.empty())que.pop();que.push(start);memset(cnt, 0, sizeof(cnt));cnt[start] = 1;while (!que.empty()){int u = que.front();que.pop();vis[u] = false;for (int i = 0; i<E[u].size(); i++){int v = E[u][i].v;if (dist[v]>dist[u] + E[u][i].cost){dist[v] = dist[u] + E[u][i].cost;if (!vis[v]){vis[v] = true;que.push(v);if (++cnt[v]>n)return false;//有负环回路}}}}return true;
}
int main()
{int T;int N, M, W;int a, b, c;scanf("%d", &T);while (T--){scanf("%d%d%d", &N, &M, &W);for (int i = 1; i <= N + 1; i++)E[i].clear();while (M--){scanf("%d%d%d", &a, &b, &c);addedge(a, b, c);addedge(b, a, c);}while (W--){scanf("%d%d%d", &a, &b, &c);addedge(a, b, -c);}for (int i = 1; i <= N; i++)addedge(N + 1, i, 0);if (!SPFA(N + 1, N + 1))printf("YES\n");else printf("NO\n");}return 0;
}

转载于:https://www.cnblogs.com/demian/p/7389260.html

POJ 3259 Wormholes(bellman_ford,判断有没有负环回路)相关推荐

  1. POJ 3259 Wormholes【最短路/SPFA判断负环模板】

    农夫约翰在探索他的许多农场,发现了一些惊人的虫洞.虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径 ...

  2. POJ - 3259 Wormholes(判断负环)

    题目链接:点击查看 题意:最短路判断负环 这里介绍三种方法判断负环,分别是spfa,bellman-ford和flyod算法,不过spfa的速度能比bellman-ford的速度慢了接近20倍是出乎 ...

  3. POJ 3259 Wormholes(负权环路)

    题意: 农夫约翰农场里发现了很多虫洞,他是个超级冒险迷,想利用虫洞回到过去,看再回来的时候能不能看到没有离开之前的自己,农场里有N块地,M条路连接着两块地,W个虫洞,连接两块地的路是双向的,而虫洞是单 ...

  4. POJ 3259 Wormholes SPFA判负环

    思路:SPFA判负环 数组不要开太小-- (后面附一组测试数组) // by SiriusRen #include <queue> #include <cstdio> #inc ...

  5. F - Wormholes(判断是否存在负环)

    ##题目描述 While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A w ...

  6. POJ 3259 Wormholes

    题目链接 题意 问是否存在负环 AC 因为Dijkstra不能处理带有负边权的图,可以用spfa 和 BellmenFord spfa using namespace std; int inf = 0 ...

  7. 【POJ/算法】 3259 Wormholes(Bellman-Ford算法, SPFA ,FLoyd算法)

    Bellman-Ford算法 Bellman-Ford算法的优点是可以发现负圈,缺点是时间复杂度比Dijkstra算法高.而SPFA算法是使用队列优化的Bellman-Ford版本,其在时间复杂度和编 ...

  8. poj 3259 时光穿梭问题 bellman_ford算法

    题意:有n个空地,有m条双向大路,w条时光隧道单向路.问能否回到过去? 思路:判断是否有负环存在,如果有负环存在那么就可以一直小就可以回到过去了 创建源顶点 V到其他顶点的距离d 初始为INF d[1 ...

  9. bellman ford 算法 判断是否存在负环

    Flyer 目录视图 摘要视图 订阅 微信小程序实战项目--点餐系统        程序员11月书讯,评论得书啦        Get IT技能知识库,50个领域一键直达 关闭 bellman for ...

最新文章

  1. 打开程序时固定位置_FANUC机器人:参考位置功能介绍与设定方法
  2. 电脑端二维码识别工具_电脑端自签工具更新,多功能软件一键签名
  3. Linux下的FTP服务
  4. Web端调用Outlook 的发信窗口
  5. 四川地震,物联网地震预警系统立功了
  6. Parallels Desktop虚拟机如何安装win10和win11,懒人安装教程
  7. python调用通达信函数_如何把通达信公式变成python
  8. django数据库迁移
  9. 网易有道词典识别不了adobe打开的pdf
  10. 高动态范围图像(HDR)处理
  11. 渗透安全学习记录笔记
  12. 虚拟服务器登录,虚拟主机服务器登录
  13. LaTeX 数学公式和符号
  14. mini-css-extract-plugin源码解析
  15. 2019年自考计算机应用基础(实践),2019年自考计算机应用基础试题练习(九)
  16. for和while循环
  17. python 模拟微信浏览器请求_python爬虫:使用Selenium模拟浏览器行为
  18. React Native 炫酷的动画库 实现任何AE动画 lottie-react-native
  19. 通过win32api与win32con模拟按键精灵爬取中国商标网数据
  20. Python采集网站ip代理, 检测IP代理是否可用,构建自己的ip代理池

热门文章

  1. python概念-Socket到底有多骚
  2. 远程桌面保存密码(凭据)的备份导出
  3. CodeBlocks使用第三方库(以使用pcre库为例)
  4. ArcMAP获取要素的外包多边形
  5. 带头结点的单链表的初始化,建立,插入,查找,删除
  6. 【转】使用 F#、MapReduce 和 Windows Azure 分析日志文件
  7. (89)Verilog HDL系统函数和任务:$fwrite
  8. mybatis级联查询list_MyBatis手把手跟我做系列(四) ---级联查询与懒加载
  9. java 集合操作工具包_java之操作集合的工具类--Collections
  10. 数字信号处理——巴特沃斯滤波器设计