题意: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;
}

POJ 3259 Wormholes(bellman_ford,判断有没有负环回路)的更多相关文章

  1. POJ 3259 Wormholes(最短路径,求负环)

    POJ 3259 Wormholes(最短路径,求负环) Description While exploring his many farms, Farmer John has discovered ...

  2. POJ 3259 Wormholes ( SPFA判断负环 && 思维 )

    题意 : 给出 N 个点,以及 M 条双向路,每一条路的权值代表你在这条路上到达终点需要那么时间,接下来给出 W 个虫洞,虫洞给出的形式为 A B C 代表能将你从 A 送到 B 点,并且回到 C 个 ...

  3. POJ 3259 Wormholes Bellman_ford负权回路

    Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes ...

  4. POJ No 3259 Wormholes Bellman-Ford 判断是否存在负图

    题目:http://poj.org/problem?id=3259 题意:主要就是构造图, 然后判断,是否存在负图,可以回到原点 /* 2 3 3 1 //N, M, W 1 2 2 1 3 4 2 ...

  5. POJ 3259 Wormholes【bellman_ford判断负环——基础入门题】

    链接: http://poj.org/problem?id=3259 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...

  6. POJ 3259 Wormholes(最短路,判断有没有负环回路)

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 24249   Accepted: 8652 Descri ...

  7. 最短路(Bellman_Ford) POJ 3259 Wormholes

    题目传送门 /* 题意:一张有双方向连通和单方向连通的图,单方向的是负权值,问是否能回到过去(权值和为负) Bellman_Ford:循环n-1次松弛操作,再判断是否存在负权回路(因为如果有会一直减下 ...

  8. ACM: POJ 3259 Wormholes - SPFA负环判定

     POJ 3259 Wormholes Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu   ...

  9. poj - 3259 Wormholes (bellman-ford算法求最短路)

    http://poj.org/problem?id=3259 农夫john发现了一些虫洞,虫洞是一种在你到达虫洞之前把你送回目的地的一种方式,FJ的每个农场,由n块土地(编号为1-n),M 条路,和W ...

随机推荐

  1. Hystrix介绍以及服务的降级限流熔断

    (dubbo熔断,Hystrix问的少) 无论是缓存层还是存储层都会有出错的概率,可以将它们视同为资源.作为并发量较大的系统,假如有一个资源不可用,可能会造成线程全部 hang (挂起)在这个资源上, ...

  2. Host is not allowed to connect to this MySQL server解决方法

    在装有MySQL的机器上登录MySQL mysql -u root -p密码 执行use mysql; 执行update user set host = '%' where user = 'root' ...

  3. 20155332 2016-2017-2 《Java程序设计》第7周学习总结

    20155332 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 了解Lambda语法 了解方法引用 了解Fucntional与Stream API 掌握Da ...

  4. Ubuntu16.04安装搜狗拼音输入法(中文输入法)

    虽然网上有很多教程,但是我觉得我的很适合那些真正的小白... 1.下载文件 由于我要给多台电脑安装搜狗输入法,所以用的是文件夹安装,不是命令行安装. 打开官网http://pinyin.sogou.c ...

  5. transform,变换

    1.transform属性:rotate(翻转),skew(倾斜),scale(缩放),translate(移位) 用法:transform: rotate(45deg) scale(0.5) ske ...

  6. curl命令下载jdk

    第一步:找到下载地址 第二步:下载

  7. 嵌入式系统C编程之错误处理

    前言 本文主要总结嵌入式系统C语言编程中,主要的错误处理方式.文中涉及的代码运行环境如下: 一  错误概念 1.1 错误分类 从严重性而言,程序错误可分为致命性和非致命性两类.对于致命性错误,无法执行 ...

  8. ES系列十八、FileBeat发送日志到logstash、ES、多个output过滤配置

    一.FileBeat基本概念 简单概述 最近在了解ELK做日志采集相关的内容,这篇文章主要讲解通过filebeat来实现日志的收集.日志采集的工具有很多种,如fluentd, flume, logst ...

  9. sum行列合计

    select sum(decode(cplb,'3',hj,0)) from lr_scsjdqdw t group by zcxmdm

  10. React-Native 之 项目实战(一)

    前言 本文有配套视频,可以酌情观看. 文中内容因各人理解不同,可能会有所偏差,欢迎朋友们联系我. 文中所有内容仅供学习交流之用,不可用于商业用途,如因此引起的相关法律法规责任,与我无关. 如文中内容对 ...