poj_3259 负权和环

题目大意

N个点,M条双向路径,W条单向路径。从双向路径的一端到另一端所花费时间为正值,从单向路径的源点到终点所花时间为负值。问是否存在一条从A出发,再回到A的回路,满足回到A的时间小于出发时间。

题目分析

显然为一个求含负权边的图中是否含有负权和回路。采用SPFA算法解决。

实现(c++)

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define MAX_NODE 505
#define INFINITE 1 << 30
struct Edge{
	int vertex;
	int dist;
	Edge(int v, int d) :
		vertex(v), dist(d){};
};

vector<vector<Edge> > gGraph;

int gDist[MAX_NODE];
int gUpdateTime[MAX_NODE];	//记录原点到每个点的最短路径被更新的次数,根据SPFA算法,若更新次数>n,则说明存在负环
bool Spfa(int s, int d, int n){
	queue<int> Q;

	Q.push(s);

	memset(gUpdateTime, 0, sizeof(gUpdateTime));	//每个点被更新次数
	for (int i = 1; i <= n; i++)	//初始化原点到每个点的距离
		gDist[i] = INFINITE;
	gDist[s] = 0;		

	while (!Q.empty()){
		//SPFA算法,使用一个先进先出队列。按照广度优先,每增加一层的深度,到达当前深度k。就可以确定
		//从原点开始到达该点的最短路径为k步的点。
		int v = Q.front();
		Q.pop();
		for (int i = 0; i < gGraph[v].size(); i++){
			if (gDist[gGraph[v][i].vertex] > gDist[v] + gGraph[v][i].dist){
				gDist[gGraph[v][i].vertex] = gDist[v] + gGraph[v][i].dist;
				if (++gUpdateTime[gGraph[v][i].vertex] >= n){	//存在负权和环
					return false;
				}
				Q.push(gGraph[v][i].vertex);
			}
		}
	}

	return true;		//不存在负权和环
}
int main(){
	int f;
	scanf("%d", &f);
	while (f--){
		int n, m, w, s, e, t;
		scanf("%d %d %d", &n, &m, &w);
		gGraph.clear();
		gGraph.resize(n + 1);
		for (int i = 0; i < m; i++){
			scanf("%d %d %d", &s, &e, &t);
			gGraph[s].push_back(Edge(e, t));
			gGraph[e].push_back(Edge(s, t));
		}
		for (int i = 0; i < w; i++){
			scanf("%d %d %d", &s, &e, &t);
			gGraph[s].push_back(Edge(e, -t));
		}
		if (Spfa(1, n, n)){
			printf("NO\n");
		}
		else
			printf("YES\n");
	}
	return 0;
}
时间: 2024-08-28 13:46:42

poj_3259 负权和环的相关文章

poj 3259 Wormholes 【最短路之负权环的判断】

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 54435   Accepted: 20273 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

LightOj 1074 Extended Traffic (spfa+负权环)

题目链接: http://lightoj.com/volume_showproblem.php?problem=1074 题目大意: 有一个大城市有n个十字交叉口,有m条路,城市十分拥挤,因此每一个路都有一个拥挤度,政府就出台了一个政策,对每一条路收取过路费,收取标准为(终点拥挤度 - 起点拥挤度 )3,,问每次询问m,输出1到m的最小花费,如果不能到达或者最小化费小于3的时候输出‘?’. 解题思路: 用spfa.标记负环. 1 #include <cstdio> 2 #include <

poj 3259 wormholes AC代码(负权环判断, Bellmanford)

#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string> #include<iomanip> #include<cstdlib> #include<cstdio> #include<vector> #include<algorithm> #include<cmath> #include<map> using namespa

poj_2315 最小费用最大流

题目大意 一个图上有N个顶点,从1到N标号,顶点之间存在一些无向边,边有长度,要求从顶点1走到顶点N,再从顶点N走回顶点1,其中不必要经过每个顶点,但是要求走的路径上的边只能经过一次.求出从1--->N-->1的路径的长度最小值. 题目分析 每条无向边最多只能走一次,可以视为这些边的容量只有1.题目中要求从顶点1走到N再走回顶点1,其中经过的边只能走一次,其实可以看做从顶点1出发的两条不同的路径(路径的边不能有重合)到达顶点N.那么就可以视为,从顶点1出发到达顶点N的总流量为2. 题目要求总路

Vijos1053 Easy sssp[spfa 负环]

描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一个点沿着某条路径出发, 又回到了自己, 而且所经过的边上的权和小于0, 就说这条路是一个负权回路.如果存在负权回路, 只输出一行-1;如果不存在负权回路, 再求出一个点S(1 <= S <= N)到每个点的最短路的长度. 约定: S到S的距离为0, 如果S与这个点不连通, 则输出NoPath. 格

P2136 拉近距离(spfa判负环)

洛谷—— P2136 拉近距离 题目背景 我是源点,你是终点.我们之间有负权环. ——小明 题目描述 在小明和小红的生活中,有N个关键的节点.有M个事件,记为一个三元组(Si,Ti,Wi),表示从节点Si有一个事件可以转移到Ti,事件的效果就是使他们之间的距离减少Wi. 这些节点构成了一个网络,其中节点1和N是特殊的,节点1代表小明,节点N代表小红,其他代表进展的阶段.所有事件可以自由选择是否进行,但每次只能进行当前节点邻接的.请你帮他们写一个程序,计算出他们之间可能的最短距离. 输入输出格式

poj 3259 Wormholes【spfa判断负环】

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 36729   Accepted: 13444 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

BZOJ3597 [Scoi2014]方伯伯运椰子 【二分 + 判负环】

题目链接 BZOJ3597 题解 orz一眼过去一点思路都没有 既然是流量网络,就要借鉴网络流的思想了 我们先处理一下那个比值,显然是一个分数规划,我们二分一个\(\lambda = \frac{X - Y}{k}\) 如果\(\lambda\)成立,则 \[\lambda \le \frac{X - Y}{k}\] 即 \[\lambda k + (Y - X) \le 0\] 所以我们只需要判断是否存在一种方案使得这个式子成立 依照网络流的思想,撤回流量就往反向边走,扩展流量往正向边 对于边

p3385 【模板】负环(spfa)

题目描述 毒瘤数据要求判负环 分析: 还是融合了不少题解的思想的. 负环定义: 权值和为负的环 //在网络上并没有找到一个官方定义,暂且这么理解. SPFA: 支持负边权的情况. spfa是最短路算法.如果一个环上的边权有负的,我们可以重复走这条路来获得更小的边权,所以这可以作为我们使用spfa判断负环的根据 //如果一个位置入队次数不小于n次,那它一定位于环上,所以这可以作为我们的判断标准. 听说STL的队列比较慢,换掉! 但是如果手打队列的话 队尾指针队首指针一直++根本停不下来怎么办? 我