题意:求带权值的有向环的平均值的最小值
思路:二分最小值,如果存在更小的值,那么c1+c2+...+ck < k * mid,即(c1-mid)+(c2-mid)+...(ck-mid) < 0(存在负环),判断是否存在负环即可
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
const int maxn = 55;
const double INF = 1e9 + 10;
const double eps = 1e-5;
using namespace std;
struct P {
int to;
double cost;
P(int t, double c) : to(t), cost(c) {}
};
double nec[maxn][maxn], up[maxn][maxn], d[maxn];
int vis[maxn], in[maxn];
int use[maxn];
int n, m, T, t = 1;
vector<P> G[maxn];
bool operator < (P a, P b) {
return a.cost > b.cost;
}
void init() {
for(int i = 0; i < maxn; i++)
G[i].clear();
for(int i = 0; i < maxn; i++) {
for(int j = 0; j < maxn; j++)
nec[i][j] = INF;
}
memset(in, 0, sizeof(in));
}
int topo() {
stack<int> s;
for(int i = 1; i <= n; i++) {
if(!in[i]) s.push(i);
}
while(!s.empty()) {
int p = s.top(); s.pop();
for(int i = 0; i < G[p].size(); i++) {
int u = G[p][i].to;
in[u]--;
if(!in[u]) s.push(u);
}
}
for(int i = 1; i <= n; i++) {
if(in[i]) return 1;
}
return 0;
}
int dijkstra(double mid, int st) {
fill(d, d + maxn, INF);
memset(vis, 0, sizeof(vis));
for(int i = 0; i < maxn; i++) {
for(int j = 0; j < maxn; j++) {
up[i][j] = nec[i][j] - mid;
}
}
priority_queue<P> q;
use[st] = vis[st] = 1;
d[st] = 0;
q.push(P(st, 0));
while(!q.empty()) {
P p = q.top(); q.pop();
int u = p.to;
if(d[u] < p.cost) continue;
for(int i = 0; i < G[u].size(); i++) {
P g = G[u][i];
use[g.to] = 1;
if(d[g.to] > d[u] + up[u][g.to]) {
d[g.to] = d[u] + up[u][g.to];
vis[g.to]++;
q.push(P(g.to, d[g.to]));
}
if(vis[g.to] > maxn) return 1;
}
}
return 0;
}
double solve() {
double l = 0, r = INF;
while(l + eps <= r) {
double mid = (l + r) / 2;
memset(use, 0, sizeof(use));
int sign = 0;
for(int i = 1; i <= n; i++) {
if(use[i] || !in[i]) continue;
sign = dijkstra(mid, i);
if(sign) break;
}
if(sign) r = mid - eps;
else l = mid;
}
return r;
}
int main() {
scanf("%d", &T);
while(T--) {
init();
scanf("%d %d", &n, &m);
while(m--) {
int f, tt;
double C;
scanf("%d %d %lf", &f, &tt, &C);
nec[f][tt] = min(nec[f][tt], C);
G[f].push_back(P(tt, 0));
in[tt]++;
}
int sign = topo();
printf("Case #%d: ", t++);
if(!sign) printf("No cycle found.\n");
else printf("%.2f\n", solve());
}
return 0;
}