要求给定的图的中平均权值最小的环,注意处理自环的情况就能过了。
按照w1+w2+w3+….wn < n*ave的不等式,也就是(w1-ave) + (w2-ave) +…..(wn-ave) < 0,将每条边减去ave看是否存在负权回路,然后不断二分,由于保留两位小数,所以至少二分log(10^7)= 30次。
代码:
#include <iostream> #include <sstream> #include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <string> #include <stack> #include <map> #include <cmath> #include <vector> #include <queue> #include <algorithm> #define esp 1e-6 #define pi acos(-1.0) #define pb push_back #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define mp(a, b) make_pair((a), (b)) #define in freopen("in.txt", "r", stdin); #define out freopen("out.txt", "w", stdout); #define print(a) printf("%d ",(a)); #define bug puts("********))))))"); #define stop system("pause"); #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++) #define inf 0x0f0f0f0f using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> pii; typedef vector<pii> VII; typedef vector<pii, int> VIII; typedef VI:: iterator IT; const int maxn = 100; struct Edge { int from, to; double dist; }; struct Bellman_Ford { int n, m; vector<Edge> edges; VI G[maxn]; double d[maxn]; int p[maxn]; int inq[maxn]; int cnt[maxn]; void init(int n) { this->n = n; for(int i = 0; i < n; i++) { G[i].clear(); } edges.clear(); } void add(int from, int to, double dist) { edges.pb((Edge) { from, to, dist }); m = edges.size(); G[from].pb(m-1); } bool negativeCircle(double L) { memset(cnt, 0, sizeof(cnt)); memset(inq, 0, sizeof(inq)); queue<int> q; for(int i = 0; i < n; i++) { d[i] = 0; inq[0] = 1; q.push(i); } while(!q.empty()) { int u = q.front(); q.pop(); inq[u] = 0; for(int i = 0; i < G[u].size(); i++) { Edge &e = edges[G[u][i]]; if(d[e.to] > d[u] + e.dist - L) { d[e.to] = d[u] + e.dist - L; if(!inq[e.to]) { q.push(e.to); inq[e.to] = 1; } if(++cnt[e.to] > n) { return true; } } } } return false; } } solver; int main(void) { int T; for(int t = scanf("%d", &T); t <= T; t++) { printf("Case #%d: ", t); int n, m; scanf("%d%d", &n, &m); solver.init(n); double ans = inf + 100; double l = (double)inf*10, r = 0; while(m--) { int u, v; double w; scanf("%d%d%lf", &u, &v, &w); u--, v--; if(u == v) ans = min(ans, w); solver.add(u, v, w); l = min(l, w); r = max(r, w); } int flag= 0; double mid = (l+r)/2; for(int i = 0; i < 30; i++) { if(solver.negativeCircle(mid)) flag = 1, r = mid-0.001; else l = mid+0.001; mid = (l+r)/2; } if(flag) printf("%.2f ", min(ans, mid)); else if(ans < inf) printf("%.2f ", ans); else puts("No cycle found."); } return 0; }