2022牛客多校第二场D.Link with Game Glitch

Link with Game Glitch

题意:有 \(n\) 种物品,给定 \(m\) 种交换方式,每种交换方式用 \(a,b,c,d\) 表示,表示可以用 \(b\) 按照 \(a : c\) 的比例换 \(d\) ,现在给定一个系数 \(w\),使得该比例变成 \(a : (w*c)\) ,求一个最大的 \(w\) 使得不存在一种方案可以无限换物品

知识点:建图,求负环

容易得到一种建图方式,对 \(b\)\(d\) 建立起一条边权为 \(\frac{c}{a}\) 边,然后对于 \(w\) 二分查找验证即可。但是如果这样的话,最坏就是 \(1000^n\) 的级别的乘法,会爆掉,所以可以用对数加来代替边权乘

#include <bits/stdc++.h>
#define endl '\n'
#define double long double
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, double> PID;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}

inline void solve() {
    int n, m; cin >> n >> m;
    vector<PID> g[n + 2];
    for (int i = 1; i <= m; i ++ ) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        g[b].emplace_back(d, log((double)c / (double)a));
    }
    for (int i = 1; i <= n; i ++ ) g[n + 1].emplace_back(i, 0);
    auto check = [&](double w) {
        w = log(w);
        vector<double> dis(n + 2, 1e18);
        vector<int> cnt(n + 2);
        vector<bool> vis(n + 2);
        queue<int> q;
        q.push(n + 1);
        dis[n + 1] = 0;
        vis[n + 1] = true;
        while (!q.empty()) {
            int t = q.front(); q.pop();
            vis[t] = false;
            for (auto ite : g[t]) {
                int v = ite.first;
                double tmp = ite.second;
                if (dis[v] > dis[t] + tmp + w) {
                    dis[v] = dis[t] + tmp + w;
                    cnt[v] = cnt[t] + 1;
                    if (cnt[v] > n + 1) return true;
                    if (!vis[v]) {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        return false;
    };
    double l = 0, r = 1;
    for (int i = 1; i <= 100; i ++ ) {
        double mid = (l + r) / 2;
        if (check(mid)) l = mid;
        else r = mid;
    }
    cout << l << endl;
}
signed main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    auto now = clock();
#endif
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(10);
//    int T; cin >> T;
//    while (T -- )
        solve();
#ifdef DEBUG
    cout << "============================" << endl;
    cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
    return 0;
}
posted @ 2022-07-29 20:38  Time_Limit_Exceeded  阅读(29)  评论(0编辑  收藏  举报