做題記錄 Luogu P4926
阿新 • • 發佈:2021-06-27
取對數化除為減。
或者用乘積最短路。
注意圖不一定連通。
#include<bits/stdc++.h> using namespace std; #define N 1000005 const double eps = 1e-12; struct graph { int opt, u, v; double w; }; graph g[N]; deque<int> q; int first[N], Next[N], to[N], tot; double w[N], dis[N]; int vis[N], cnt[N], score[N], n, s, t; void add(int x, int y, double z) { Next[++tot] = first[x]; first[x] = tot; to[tot] = y; w[tot] = z; return; } int spfa(int x, double mid) { for(int i = 0; i <= n; i++) { dis[i] = 1; q.push_front(i); } memset(vis, 0, sizeof(vis)); memset(cnt, 0, sizeof(cnt)); vis[x] = 1; while(!q.empty()) { int u = q.front(); q.pop_front(); vis[u] = 0; for(int i = first[u]; i; i = Next[i]) { int v = to[i]; if(dis[u] * w[i] > dis[v]) { dis[v] = dis[u] * w[i]; if(!vis[v]) { if(++cnt[v] >= n + 1) { return 0; } vis[v] = 1; if(q.empty() || dis[v] < dis[q.front()]) { q.push_front(v); } else { q.push_back(v); } } } } } return 1; } int check(double mid) { tot = 0; memset(first, 0, sizeof(first)); while(!q.empty()) { q.pop_front(); } for(int i = 1; i <= s; i++) { if(g[i].opt == 1) { add(g[i].v, g[i].u, g[i].w - mid); } else { add(g[i].v, g[i].u, 1.0 / (g[i].w + mid)); } } for(int i = 1; i <= n; i++) { if(score[i]) { add(0, i, score[i]); add(i, 0, 1.0 / score[i]); } } return spfa(0, mid); } int main() { scanf("%d%d%d", &n, &s, &t); for(int i = 1; i <= s; i++) { scanf("%d%d%d%lf", &g[i].opt, &g[i].u, &g[i].v, &g[i].w); } int k, x; for(int i = 1; i <= t; i++) { scanf("%d%d", &k, &x); score[k] = x; } double l = 0, r = 1e9, mid, ans = -1; while(r - l > eps) { mid = (l + r) / 2; if(!check(mid)) { l = ans = mid; } else { r = mid; } } printf("%lf", ans); }