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;
}
原文地址:https://www.cnblogs.com/HarryGuo2012/p/4749430.html