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