UVa 11090 - Going in Cycle!! (01分數規劃)
阿新 • • 發佈:2021-07-18
題目連結:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=2031&mosmsg=Submission+received+with+ID+26584370
求有向圖平均權最小的迴路
二分答案 \(x\),將所有邊都減去 \(x\),看圖中是否有負環即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 105; const double eps = 1e-3; int T, n, m; int h[maxn], cnt = 0; struct E{ int to, next; double cost; }e[maxn * maxn]; void add(int u, int v, double w){ e[++cnt].to = v; e[cnt].cost = w; e[cnt].next = h[u]; h[u] = cnt; } int in[maxn], tot[maxn]; double d[maxn]; bool spfa(double mid){ queue<int> q; memset(tot, 0, sizeof(tot)); memset(in, 0, sizeof(in)); for(int i = 1 ; i <= n ; ++i) { d[i] = 0; in[i] = 1; q.push(i); } while(!q.empty()){ int u = q.front(); q.pop(); in[u] = 0; for(int i = h[u] ; i != -1 ; i = e[i].next){ int v = e[i].to; if(d[u] + e[i].cost - mid - d[v] < 0){ d[v] = d[u] + e[i].cost - mid; if(!in[v]){ in[v] = 1; q.push(v); ++tot[v]; if(tot[v] > n) return false; } } } } return true; } bool check(double x){ return !spfa(x); } ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; } int main(){ scanf("%d", &T); int kase = 0; while(T--){ memset(h, -1, sizeof(h)); cnt = 0; scanf("%d%d", &n, &m); int u, v; double w; double L = 0, R = 0; for(int i = 1 ; i <= m ; ++i){ scanf("%d%d%lf", &u, &v, &w); add(u, v, w); R = max(R, w * 1.0); } printf("Case #%d: ", ++kase); if(!check(R + 1.0)) printf("No cycle found.\n"); else { double ans = 0; while(R - L > eps){ double mid = (R + L) / 2; if(check(mid)){ R = mid; } else{ L = mid; } } printf("%.2lf\n", L); } } return 0; }