p11090_page-0001.jpg

 

题意:给定一个有向图,求边权平均值最小的环的边权平均值。

二分

若环平均值等于mid,则 w1+w2++wkmidkw_1+w_2+\cdots +w_k\geq mid\cdot k,即 (w1mid)+(w2mid)++(wkmid)0(w_1-mid)+(w_2-mid)+\cdots +(w_k-mid)\geq 0,即没有负环,所以如果有负环,则表明该环平均值小于mid。

用Bellman判负环即可。

注意有负环和有负权边是不同的!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int maxn = 110;
const double eps = 1e-5;
int T, n, m;
struct edge
{
int from, to, dist;
};
struct Bellman
{
int n, m;
vector<edge>edges;
vector<int>G[maxn];
bool inq[maxn];
double d[maxn];
int p[maxn], cnt[maxn];
void init(int n) {
this->n = n;
for (int i = 1; i <= n; i++)G[i].clear();
edges.clear();
}
void add_edge(int u, int v, int dist) {
edges.push_back(edge{ u,v,dist });
m = edges.size();
G[u].push_back(m - 1);
}
bool negative(double ad) {
queue<int>Q;
memset(inq, 0, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; i++) {
d[i] = 0;
inq[i] = true;
Q.push(i);
}
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = false;
for (int i = 0; i < G[u].size(); i++) {
edge& e = edges[G[u][i]];
if (d[e.to] > d[u] + e.dist - ad) {
d[e.to] = d[u] + e.dist - ad;
p[e.to] = G[u][i];
if (!inq[e.to]) {
Q.push(e.to);
inq[e.to] = true;
if (++cnt[e.to] > n)return true;
}
}
}
}
return false;
}
};
Bellman bell;
int main() {
scanf("%d", &T);
for (int tt = 1; tt <= T; tt++) {
scanf("%d%d", &n, &m);
bell.init(n);
for (int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
bell.add_edge(u, v, w);
}
double l = 0, r = 1e7 + 5;
while (r - l > eps) {
double mid = (l + r) / 2;
if (bell.negative(mid))r = mid;
else l = mid + eps;
}
printf("Case #%d: ", tt);
if (r == 1e7 + 5)printf("No cycle found.\n");
else {
printf("%.2f\n", l);
}
}
return 0;
}