n个点m条边的无向图,每条路有固定的长度,然后有一个速度上限。要求在T时间内能从1到达n,最少超速多少?
显然是二分答案然后求最短路。不过当二分枚举的超速很大而某条边的距离很小的时候,经过这条边的时间是会很小很小的,所以要将所有的时间单位扩大1e9倍,才不会丢失精度。。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<fstream>
#include<sstream>
#include<cstdlib>
#include<vector>
#include<string>
#include<cstdio>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#define FF(i, a, b) for(int i=a; i<b; i++)
#define FD(i, a, b) for(int i=a; i>=b; i--)
#define REP(i, n) for(int i=0; i<n; i++)
#define CLR(a, b) memset(a, b, sizeof(a))
#define debug puts("**debug**")
#define LL long long
#define PB push_back
#define MP make_pair
using namespace std;
const double INF = 1e50;
const int maxn = 10010;
const double eps = 1e-7;
struct Edge
{
int from, to;
double dist;
Edge(){}
Edge(int a, int b, double c):from(a), to(b), dist(c){}
};
struct Heap
{
double d;
int u;
Heap(){}
Heap(double d, int u):d(d), u(u){}
bool operator<(const Heap& rhs) const
{
return d > rhs.d;
}
};
map<int, int> mp;
bool flag;
struct Dijkstra
{
int n, m;
vector<int> G[maxn];
vector<Edge> edges;
bool done[maxn];
double d[maxn];
int p[maxn];
void init(int n)
{
this->n = n;
REP(i, n+1) G[i].clear();
edges.clear();
}
void add(int a, int b, double c, int id)
{
Edge e1 = Edge(a, b, c), e2 = Edge(b, a, c);
edges.PB(e1), edges.PB(e2);
m = edges.size();
G[a].PB(m-2), G[b].PB(m-1);
if(!flag) mp[m-2] = mp[m-1] = id;
}
void dijkstra(int s)
{
priority_queue<Heap> q;
REP(i, n+1) d[i] = INF;
d[s] = 0; CLR(done, 0);
q.push(Heap(0, s));
while(!q.empty())
{
Heap x = q.top(); q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = 1;
REP(i, G[u].size())
{
Edge e = edges[G[u][i]];
if(d[e.to] > d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
q.push(Heap(d[e.to], e.to));
}
}
}
}
void getpath(int s, int t, vector<int>& path)
{
while(t != s)
{
path.PB(p[t]);
t = edges[p[t]].from;
}
reverse(path.begin(), path.end());
}
}solver;
int n, m;
double T;
struct E
{
int u, v;
double s, l;
}e[maxn];
bool ok(double mid)
{
solver.init(n);
FF(i, 1, m+1) solver.add(e[i].u, e[i].v, e[i].l/(e[i].s+mid)*1000000000, i);
solver.dijkstra(1);
flag = 1;
return solver.d[n] <= T;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
mp.clear();
flag = 0;
FF(i, 1, m+1) scanf("%d%d%lf%lf", &e[i].u, &e[i].v, &e[i].s, &e[i].l);
scanf("%lf", &T);
T *= 1000000000;
double L = 0, R = 1e8, M;
while(L + eps < R)
{
M = (L + R) / 2;
if(ok(M)) R = M;
else L = M;
}
printf("%.6lf ", L);
vector<int> path;
solver.getpath(1, n, path);
int nc = path.size();
printf("%d\n", nc);
REP(i, nc) printf("%d%c", mp[path[i]], i == nc-1 ? '\n' : ' ');
}
return 0;
}