标签:连通 ++ bit || scanf ref while eps namespace
取对数化除为减。
或者用乘积最短路。
注意图不一定连通。
#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);
}
标签:连通 ++ bit || scanf ref while eps namespace
原文地址:https://www.cnblogs.com/fanypcd/p/14940626.html