UVA - 11090 Going in Cycle!! (Bellman-Ford算法判负环)

Description


I I
U P C
2 0
06


Problem G: Going in Cycle!!


Input: standard input

Output: standard output


You are given a weighted directed graph with n vertices and
m
edges. Each cycle in the graph has a weight, which equals to sum of its edges. There are so many cycles in the graph with different weights. In this problem we want to find a cycle with the minimum mean.


Input


The first line of input gives the number of cases, N.
N
test cases follow. Each one starts with two numbers n and
m. m lines follow, each has three positive number
a, b, c which means there is an edge from vertex a to
b with weight of c.

Output


For each test case output one line containing “Case #x: ” followed by a number that is the lowest mean cycle in graph with 2 digits after decimal place, if there is a cycle. Otherwise print “No cycle found.”.


Constraints


-           n ≤ 50

-           a, b ≤ n

-           c ≤ 10000000


Sample Input


Output for Sample Input


2

2 1

1 2 1

2 2

1 2 2

2 1 3


Case #1: No cycle found.

Case #2: 2.50

题意:给定一个n个点m条边的加权有向图,求平均权值最小的回路。

思路:先使用二分求解mid。假设存在一个包含k条边的回路,回路上各个边的权值为w1,w2....wk,那么平均值小于mid

意味着:w1+w2..+wk<K*mid -> (w1-mid)+(w2-mid)+...(wk-mid) < 0,就是判断新图中是否含有负权回路了,两种初始化结果都对

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 60;
const int inf = 0x3f3f3f3f;

struct Edge {
	int from, to;
	double dist;
};

struct BellmanFord {
	int n, m;
	vector<Edge> edges;
	vector<int> G[maxn];
	bool inq[maxn];
	double d[maxn];
	int p[maxn];
	int cnt[maxn];

	void init(int n) {
		this->n = n;
		for (int i = 0; i < n; i++)
			G[i].clear();
		edges.clear();
	}

	void AddEdge(int from, int to, int dist) {
		edges.push_back((Edge){from, to, dist});
		m = edges.size();
		G[from].push_back(m-1);
	}

	bool negativeCycle() {
		queue<int> Q;
		memset(inq, 0, sizeof(inq));
		memset(cnt, 0, sizeof(cnt));
	/*	for (int i = 0; i < n; i++) {
			d[i] = 0;
			inq[0] = 1;
			Q.push(i);
		}
		*/
		for (int i = 0; i < n; i++) {
			d[i] = 0;
			inq[i] = 1;
			Q.push(i);
			cnt[i] = 1;
		}

		while (!Q.empty()) {
			int u = Q.front();
			Q.pop();
			inq[u] = 0;
			for (int i = 0; i < G[u].size(); i++) {
				Edge &e = edges[G[u][i]];
				if (d[e.to] > d[u] + e.dist) {
					d[e.to] = d[u] + e.dist;
					p[e.to] = G[u][i];
					if (!inq[e.to]) {
						Q.push(e.to);
						inq[e.to] = 1;
						if (++cnt[e.to] > n)
							return 1;
					}
				}
			}
		}
		return 0;
	}
};
BellmanFord solver;

bool test(double x) {
	for (int i = 0; i < solver.m; i++)
		solver.edges[i].dist -= x;
	bool ret = solver.negativeCycle();
	for (int i = 0; i < solver.m; i++)
		solver.edges[i].dist += x;
	return ret;
}

int main() {
	int t;
	scanf("%d", &t);
	for (int cas = 1; cas <= t; cas++) {
		int n, m;
		scanf("%d%d", &n, &m);
		solver.init(n);
		int ub = 0;
		while (m--) {
			int u, v, w;
			scanf("%d%d%d", &u, &v, &w);
			u--, v--;
			ub = max(ub, w);
			solver.AddEdge(u, v, w);
		}
		printf("Case #%d: ", cas);
		if (!test(ub+1))
			printf("No cycle found.\n");
		else {
			double L = 0, R = ub;
			while (R-L > 1e-3) {
				double M = L + (R-L)/2;
				if (test(M))
					R = M;
				else L = M;
			}
			printf("%.2lf\n", L);
		}
	}
	return 0;
}

UVA - 11090 Going in Cycle!! (Bellman-Ford算法判负环)

时间: 2024-10-17 12:11:30

UVA - 11090 Going in Cycle!! (Bellman-Ford算法判负环)的相关文章

POJ 3259 Wormholes (bellman_ford算法判负环)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 32393   Accepted: 11771 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

UVA 11090 - Going in Cycle!!(Bellman-Ford)

UVA 11090 - Going in Cycle!! 题目链接 题意:给定一个有向图,球平均权值最小的回路 思路:二分+判负环,每次二分一个值mid,判断是否存在小于mid的环,那么就是(w1 + w2 + w3...) / n < mid == w1 - mid + w2 - mid + w3 - mid .... < 0,所以每次二分的时候,把边权值减掉mid,之后bellmanford判负环即可 代码: #include <cstdio> #include <cst

Bellman - Ford 算法解决最短路径问题

Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力不从心了,而Bellman - Ford算法可以解决这种问题. Bellman - Ford 算法可以处理路径权值为负数时的单源最短路径问题.设想可以从图中找到一个环路且这个环路中所有路径的权值之和为负.那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去.如果不处理这个负环路,程序就会永远运

UVA 11090 - Going in Cycle!!

二分+SPFA找负环 11090 - Going in Cycle!! Time limit: 3.000 seconds I I U P C 2 0 0 6 Problem G: Going in Cycle!! Input: standard input Output: standard output You are given a weighted directed graph with n vertices and m edges. Each cycle in the graph has

Bellman—Ford算法思想

---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G运行Bellman—Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路.若存在负权回路,单源点最短路径问题无解:若不存在这样的回路,算法将给出从源点s到图G的任意顶点v的最短路径值d[v] Bellman—Ford算法流程 分为三个阶段: (1)初始化:将除源点外的所有顶点

训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环)

layout: post title: 训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - BellmanFord - 图论 - 训练指南 Going in Cycle!! UVA - 11090 题意 就最小的环的平均权值 题解 分枚举平均值mid,只需判断是否存在平均值小于mid的回路,即判断是否有sum(wi)&

uva11090 Going in Cycle!! --- 二分+spfa判负环

给一个带权有向图,求其中是否存在环,若存在,输出环上边权的平均值最小的那个的平均值. 点的范围就50,感觉可以很暴力..但显然超时了 感觉方法好巧妙,二分平均值,将所有边权减去二分的那个值,然后spfa判断是否有负环 若有负环,则图中存在的所有环的边权平均值一定比枚举值大 反之则小,要是无论枚举值多大都没有负环,说明图中没有环. #include <iostream> #include <cstring> #include <string> #include <c

UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)

题意:给定一个n个点m条边的带权有向图,求平均权值最小的回路的平均权值? 思路:首先,图中得有环的存在才有解,其次再解决这个最小平均权值为多少.一般这种就是二分猜平均权值了,因为环在哪也难以找出来,还有可能是一条边属于多个环.对于每个猜到的平均值,如果对应环的存在,那么这个环的每条边的权减去这个平均值之后,用spfa算法就能判断其是否有环的存在即可. 假设环上各边权值为:w1+w2+...+wk. 式子:w1+w2+...+wk<k*even   相当于   (w1-even)+(w2-even

UVa 11090 Going in Cycle!!【Bellman_Ford】

题意:给出n个点m条边的加权有向图,求平均值最小的回路 自己想的是用DFS找环(真是too young),在比较找到各个环的平均权值,可是代码实现不了,觉得又不太对 后来看书= =好巧妙的办法, 使用二分法求解,首先记录下来这m条边的最大权值ub 然后可以猜测一个mid,只需要判断是否存在平均值小于mid的回路 假设存在一个包含k条边的回路,回路上各条边的权值分别为w1,w,2,w3,----,wk 那么 w1+w2+w3+----+wk<k*mid 又因为联想到Bellman_Ford可以解决