UVA 11090 Going in Cycle!! SPFA判断负环+二分
原题链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2031
题意
给你一个有向图,问你定义一个环的平均值为这个环上所有边的平均值,问你最小的环的平均值是多少。
题解
一种做法是强行把所有环搞出来,然后检查即可。不过这种做法好难写。。。。
我的做法是二分答案:若当前的二分值是mid,让所有的边都减去这个值,如果此时图中出现负环,则说明有环的平均值比这个更小(为什么请脑补)。
代码
#include<iostream> #include<vector> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<iomanip> #include<cstdio> #define MAX_N 66 #define INF 50000000000 #define eps 1e-4 using namespace std; typedef long long ll; int T; int n,m; struct edge { public: int to; double cost; edge(int t, double c) : cost(c), to(t) { } edge() { } }; vector<edge> G[MAX_N]; int cas = 0; queue<int> que; bool inQue[MAX_N]; double d[MAX_N]; int cnt[MAX_N]; bool vis[MAX_N]; bool spfa(int s) { fill(d, d + n + 1, INF); while (que.size())que.pop(); memset(inQue, 0, sizeof(inQue)); que.push(s); inQue[s] = 1; d[s] = 0; memset(cnt, 0, sizeof(cnt)); cnt[s]++; while (que.size()) { int u = que.front(); vis[u]=1; que.pop(); inQue[u] = 0; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].to; double t = G[u][i].cost + d[u]; if (t < d[v]) { d[v]=t; if(!inQue[v]) { que.push(v); inQue[v] = 1; cnt[v]++; if (cnt[v] > n)return true; } } } } return false; } bool check(double mid) { for (int i = 1; i <= n; i++) for (int j = 0; j < G[i].size(); j++) G[i][j].cost -= mid; bool flag; memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++) { if (!vis[i]) { flag = spfa(i); if(flag)break; } } for (int i = 1; i <= n; i++) for (int j = 0; j < G[i].size(); j++) G[i][j].cost += mid; return flag; } int main() { cin.sync_with_stdio(false); cin >> T; while (T--) { cin >> n >> m; for (int i = 0; i <= n; i++)G[i].clear(); int u, v; double c; for (int i = 0; i < m; i++) { cin >> u >> v >> c; G[u].push_back(edge(v, c)); } double l = 0, r = 10000005; while (l + eps < r) { double mid = (l + r) / 2; if (check(mid))r = mid; else l = mid; } if (!(fabs(r-10000005)<eps)) cout << "Case #" << ++cas << ": " << setprecision(2) << fixed << l << endl; else cout << "Case #" << ++cas << ": No cycle found." << endl; } return 0; }