题意: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. Docker 入门 第五部分:Stacks

    目录 Docker 入门 第五部分:Stacks 先决条件 介绍 添加一个新的服务并重新部署 保存数据 回顾 Docker 入门 第五部分:Stacks 先决条件 安装 Docker 1.13 或更高 ...

  2. dijkstra补充

    dijkstra主要写法: priority_queue<pair<int,int> >q; //大根堆 //dis第一维为dis的相反数 void dijkstra(){ m ...

  3. dense prediction

    Dense prediction  fully convolutional network for sementic segmentation 先用feature extractor 提特征,然后再使 ...

  4. 图片和流的相互转化 (c/s)

    //图片转化为流保存: Stream ms; byte[] picbyte; OpenFileDialog open = new OpenFileDialog(); open.Filter = &qu ...

  5. Linux 查看文件编码

    查看某个文件的编码格式:使用 vi 编辑器 打开文件: 按 Esc 输入 ” : set fileencoding “ 就会显示出来 文件的编码格式 : set fileencoding

  6. 主窗口QMainWindow和启动画面

    在较为大型复杂,功能较多的应用程序中,我们通常继承QMainWindow类来进行开发.该主窗口为搭建应用用户界面提供了非常好的框架,请看下图: 可以看出该主窗口类为我们提供了菜单栏(Menu Bar) ...

  7. 下拉选择框QCombox

    下拉列表框样式如图: 字体列表框样式: import sys from PyQt5.QtWidgets import QApplication, QWidget, QComboBox, QFontCo ...

  8. mysql 8.0 ~ 安装

    1 环境配置   wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.13-linux-glibc2.12-x86_64.tar. ...

  9. mysql 原理 ~ 常规锁

    一 模式 RR模式二 mysql锁相关场景  1 有间隙的地方就可能有间隙锁,并非只有辅助索引的场景下才会存在gap lock,典型场景 id主键的范围查询  2 varchar的范围锁定原理和int ...

  10. strong、weak、copy、assign 在命名属性时候怎么用

    一直都在疑惑属性定义中在什么情况下用strong.在什么情况下用weak? 总结大致如下: 1.weak 是用来修饰代理(delegate)和UI控件. 2.strong 是用来修饰除了代理(dele ...