题意: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. PHP7 学习笔记(十)会话控制

    防守打法 1.设置Cookie,[基于内存的Cookie] setcookie('Username','tinywan'); setcookie('Age','24'); 2.查看Cookie存储位置 ...

  2. 如何在同一台服务器上部署两个tomcat

    因为测试的需要,有时我们必须在同一个服务器上部署两个tomcat,然后去做应用的部署,那么很多同学可能会觉得比较为难,找的资料也比较的不齐全,那么今天华华就来给大家讲讲如何部署2个tomcat,并能够 ...

  3. B - Fuzzy Search (FFT)

    题目链接:https://cn.vjudge.net/contest/281959#problem/B 题目大意:给你n,m,k.然后输入两个字符串,n代表第一个字符串s1,m代表第二个字符串s2,然 ...

  4. SpringMVC的JSON数据交互(七)-@Response,@RestController,@RequestBody用法

    1.@RequestBody   (自动将请求的数据封装为对象) 作用: @RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConve ...

  5. 使用Groovy的sql模块操作mysql进行多种查询

    连接数据库,这里要创建一个sql实例来操作数据库,必须加载jdbc驱动包,使用两个注解,否则会报错: import groovy.sql.Sql url='jdbc:mysql://localhost ...

  6. jquery插件模式开发和react组件开发之间的异同

    jquery插件模式开发和react组件开发之间的异同

  7. ES系列十一、ES的index、store、_source、copy_to和all的区别

    1.基本概念 1.1._source 存储的原始数据._source中的内容就是搜索api返回的内容,如: { "query":{  "term":{   &q ...

  8. Python3学习笔记19-继承和多态

    在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承, 新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Sup ...

  9. lnmp使用socket方式连接nginx优化php-fpm性能

    lnmp使用socket方式连接nginx优化php-fpm性能 Nginx连接fastcgi的方式有2种:TCP和unix domain socket 什么是Unix domain socket?- ...

  10. centos6环境创建局域网http方式的yum源

    环境: yum服务器:centos 6.3 :192.168.8.20 yum源客户端:centos6.5 使用的主要rpm包来自centos6.5光盘 yum源服务器端配置: 1. 首先需要检查一下 ...