POJ 3259 Wormholes(bellman_ford,判断有没有负环回路)
题意: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,判断有没有负环回路)的更多相关文章
- POJ 3259 Wormholes(最短路径,求负环)
POJ 3259 Wormholes(最短路径,求负环) Description While exploring his many farms, Farmer John has discovered ...
- POJ 3259 Wormholes ( SPFA判断负环 && 思维 )
题意 : 给出 N 个点,以及 M 条双向路,每一条路的权值代表你在这条路上到达终点需要那么时间,接下来给出 W 个虫洞,虫洞给出的形式为 A B C 代表能将你从 A 送到 B 点,并且回到 C 个 ...
- POJ 3259 Wormholes Bellman_ford负权回路
Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes ...
- 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 ...
- POJ 3259 Wormholes【bellman_ford判断负环——基础入门题】
链接: http://poj.org/problem?id=3259 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...
- POJ 3259 Wormholes(最短路,判断有没有负环回路)
Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 24249 Accepted: 8652 Descri ...
- 最短路(Bellman_Ford) POJ 3259 Wormholes
题目传送门 /* 题意:一张有双方向连通和单方向连通的图,单方向的是负权值,问是否能回到过去(权值和为负) Bellman_Ford:循环n-1次松弛操作,再判断是否存在负权回路(因为如果有会一直减下 ...
- ACM: POJ 3259 Wormholes - SPFA负环判定
POJ 3259 Wormholes Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu ...
- poj - 3259 Wormholes (bellman-ford算法求最短路)
http://poj.org/problem?id=3259 农夫john发现了一些虫洞,虫洞是一种在你到达虫洞之前把你送回目的地的一种方式,FJ的每个农场,由n块土地(编号为1-n),M 条路,和W ...
随机推荐
- Java NIO 机制分析(一) Java IO的演进
一.引言 Java1.4之前的早期版本,Java对I/O的支持并不完善,开发人员再开发高性能I/O程序的时候,会面临一些巨大的挑战和困难,主要有以下一些问题: (1)没有数据缓冲区,I/O性能存在问题 ...
- IntelliJ IDEA 界面介绍及常用配置
一:配置Maven File-->Settings-->搜索框输入maven -->配置maven home directory 跟 user setting file 二:配置JD ...
- Docker 入门 第五部分:Stacks
目录 Docker 入门 第五部分:Stacks 先决条件 介绍 添加一个新的服务并重新部署 保存数据 回顾 Docker 入门 第五部分:Stacks 先决条件 安装 Docker 1.13 或更高 ...
- ATS 自定义日志格式
字段解释 %<chi> 客户端IP %<caun> The username of the authenticated client. A hyphen (-) means t ...
- Visual Studio 各版本下载
http://baike.baidu.com/link?url=guN2bFtq-TvtdH-iDSiYFDJ-HF8R4_12qz6QRjxKxP2Nz8jK0p70KlmudolZOg-C3umq ...
- luogu P2508 [HAOI2008]圆上的整点
传送门 推荐去bzoj看个视频了解一下 不要妄想视频直接告诉你题解 但是视频告诉了你后面要用的东西 首先我们要求的是\(x^2+y^2=n^2(x,y\in Z)\)的\((x,y)\)对数,可以转化 ...
- Python 入门基础13 --模块与包
本节内容: 一.模块及使用 1.模块及使用 2.起别名.from导入 3.自执行与模块 二.包的使用 2.1 包中模块的使用:import 2.2 包的嵌套 2.3 包中模块的使用:from ...i ...
- 2017-2018-2 20155303『网络对抗技术』Final:Web渗透获取WebShell权限
2017-2018-2 『网络对抗技术』Final:Web渗透获取WebShell权限 --------CONTENTS-------- 一.Webshell原理 1.什么是WebShell 2.We ...
- Debian 安装配置(包括kdevelop)
最近几天折腾了一下Debian 7 (gnome桌面DVD版,KDE桌面CD版最后会提到),总的来说收获还是挺大的,对比以前使用ubuntu,debian 7给我的感觉像是一个新生婴儿,不带多余的花俏 ...
- 【转】Python之文件读写
[转]Python之文件读写 本节内容: I/O操作概述 文件读写实现原理与操作步骤 文件打开模式 Python文件操作步骤示例 Python文件读取相关方法 文件读写与字符编码 一.I/O操作概述 ...