https://vjudge.net/problem/UVA-11090
题意:
给定一个n个点m条边的加权有向图,求平均权值最小的回路。
思路:
二分枚举,只需要把每条边的权值变为w-mid,之后判断是否存在负圈即可。
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6 using namespace std; 7 8 const int maxn = 50 + 5; 9 10 int n, m; 11 12 struct Edge 13 { 14 int from, to; 15 double dist; 16 Edge(int u, int v, double d) :from(u), to(v), dist(d){} 17 }; 18 19 struct BellmanFord 20 { 21 int n, m; 22 vector<Edge> edges; 23 vector<int> G[maxn]; 24 bool inq[maxn]; 25 double d[maxn]; 26 int p[maxn]; 27 int cnt[maxn]; 28 29 void init(int n) 30 { 31 this->n = n; 32 for (int i = 0; i < n; i++) 33 G[i].clear(); 34 edges.clear(); 35 } 36 37 void AddEdge(int from, int to, double dist) 38 { 39 edges.push_back(Edge(from, to, dist)); 40 int m = edges.size(); 41 G[from].push_back(m - 1); 42 } 43 44 bool negativeCycle() 45 { 46 queue<int> Q; 47 memset(inq, 0, sizeof(inq)); 48 memset(cnt, 0, sizeof(cnt)); 49 for (int i = 0; i < n; i++) 50 { 51 d[i] = 0; inq[0] = true; Q.push(i); 52 } 53 54 while (!Q.empty()) 55 { 56 int u = Q.front(); 57 Q.pop(); 58 inq[u] = false; 59 for (int i = 0; i < G[u].size(); i++) 60 { 61 Edge& e = edges[G[u][i]]; 62 if (d[e.to]>d[u] + e.dist) 63 { 64 d[e.to] = d[u] + e.dist; 65 p[e.to] = e.from; 66 if (!inq[e.to]) 67 { 68 Q.push(e.to); 69 inq[e.to] = true; 70 if (++cnt[e.to] > n) return true; 71 } 72 } 73 } 74 } 75 return false; 76 } 77 }solver; 78 79 bool test(double x) 80 { 81 for (int i = 0; i < m; i++) 82 solver.edges[i].dist -= x; 83 bool ret = solver.negativeCycle(); 84 for (int i = 0; i < m; i++) 85 solver.edges[i].dist += x; 86 return ret; 87 } 88 89 int main() 90 { 91 //freopen("D:\input.txt", "r", stdin); 92 int T; 93 int u, v, d; 94 scanf("%d", &T); 95 for (int kase = 1; kase <= T; kase++) 96 { 97 scanf("%d%d", &n, &m); 98 solver.init(n); 99 int ub = 0; 100 for (int i = 0; i < m; i++) 101 { 102 scanf("%d%d%d", &u, &v, &d); 103 ub = max(ub, d); 104 solver.AddEdge(u - 1, v - 1, d); 105 } 106 printf("Case #%d: ", kase); 107 if (!test(ub + 1)) printf("No cycle found. "); 108 else 109 { 110 double L = 0, R = ub; 111 while (R - L > 1e-3) 112 { 113 double M = L + (R - L) / 2; 114 if (test(M)) R = M; 115 else L = M; 116 } 117 printf("%.2lf ", L); 118 } 119 } 120 return 0; 121 }