UVa 11090 Going in Cycle! BellmanFord 判負權環
阿新 • • 發佈:2019-01-30
題目大意:
給你一個由n個點,m條邊組成的有向圖,求圖中最小環的平均長度。
分析:
根據最小環的條件,我們可以通過二分的方法來實現,對於每個當前二分出來的答案,要使得環上的每一條邊的平均值小於當前答案,就等價於
進一步可以推匯出:
所以說,只要把每一條邊的權值減去mid再判斷新圖中是否存在負權環即可。
程式碼:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 60;
struct Edge { int from, to; double dist; };
struct BellmanFord {
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
bool inque[maxn];
double dis[maxn];
int pre[maxn], cnt[maxn];
void init(int n) {
this->n = n;
for(int i=0; i<n; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, double dist) {
edges.push_back((Edge){from, to, dist});
m = edges.size();
G[from].push_back(m-1);
}
bool negativeCycle() {
queue<int> q;
memset(cnt, 0, sizeof(cnt));
memset(inque, false, sizeof(inque));
for (int i=0; i<n; i++) dis[i] = 0, q.push(i), inque[i] = true;
while(!q.empty()) {
int u = q.front(); q.pop(); inque[u] = false;
for(int i=0; i<(int)G[u].size(); i++) {
Edge& e = edges[G[u][i]];
if(dis[e.to] > dis[u] + e.dist) {
dis[e.to] = dis[u] + e.dist;
if(!inque[e.to]) {
q.push(e.to);
pre[e.to] = G[u][i];
inque[e.to] = true;
if(++cnt[e.to] > n) return true;
}
}
}
}
return false;
}
}Bel;
bool check(double mid) {
for(int i=0; i<Bel.m; i++)
Bel.edges[i].dist -= mid;
bool res = Bel.negativeCycle();
for(int i=0; i<Bel.m; i++)
Bel.edges[i].dist += mid;
return res;
}
double binary_search(double L, double R) {
while(R - L > 1e-5) {
double M = L + (R-L)/2;
if(check(M)) R = M; else L = M;
}
return L;
}
int Case, T, n, m, u, v, w;
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt", "r", stdin);
freopen("ans.txt", "w", stdout);
#endif
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
Bel.init(n);
double L = 0, R = 0;
for(int i=0; i<m; i++) {
scanf("%d%d%d", &u, &v, &w);
u--, v--, R = R < w ? w : R;
Bel.AddEdge(u, v, w);
}
printf("Case #%d: ", ++Case);
if(!check(R + 1)) { printf("No cycle found.\n"); continue; }
double ans = binary_search(L, R);
printf("%.2f\n", ans);
}
return 0;
}