思路:
二分答案 + spfa判负环
#pragma GCC optimize(2)#pragma GCC optimize(3)#pragma GCC optimize(4)#includeusing namespace std;#define fi first#define se second#define pi acos(-1.0)#define LL long long//#define mp make_pair#define pb push_back#define ls rt<<1, l, m#define rs rt<<1|1, m+1, r#define ULL unsigned LL#define pll pair #define pli pair #define pii pair #define piii pair #define mem(a, b) memset(a, b, sizeof(a))#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);//headconst int N = 55;const double eps = 1e-4;vector g[N];bool vis[N];double dis[N];int n;bool spfa(int u, double x) { vis[u] = true; for (pii e : g[u]) { int v = e.fi; if(dis[u] + (double)e.se - x < dis[v]) { dis[v] = dis[u] + e.se - x; if(vis[v]) return true; if(spfa(v, x)) return true; } } vis[u] = false; return false;}bool check(double x) { mem(vis, false); for (int i = 1; i <= n; i++) dis[i] = 0; for (int i = 1; i <= n; i++) if(spfa(i, x)) return true; return false;}int main() { int T, m, u, v, w; scanf("%d", &T); for (int cs = 1; cs <= T; cs++) { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) g[i].clear(); double sum = 0; for (int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); g[u].pb(pii{v, w}); sum += w; } double l = 0, r = sum+1, mid = (l+r)/2; while(l + eps < r) { if(check(mid)) r = mid; else l = mid; mid = (l+r)/2; } if(check(r)) printf("Case #%d: %.2f\n", cs, mid);//检查右端点来判负环 else printf("Case #%d: No cycle found.\n", cs); } return 0;}