zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    获取系统DPI、系统显示比例等
    [LeetCode] 698. Partition to K Equal Sum Subsets
    .NET Framework基础知识(二)(转载)
    linux week3
    多进程
    Python 析构方法__del__
    面向对象作业
    网页视频加速播放
    javaScript(5)---运算符
    javaScript(5)---运算符
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4749430.html
Copyright © 2011-2022 走看看