浙大集训day3:A
目前情况非常危险:
B和M都是玩家,另一个人是冒名顶替者。
冒名顶替者一旦和两个人的位置重合,就可以杀死其中一个人。
给出两个人的起点,冒名顶替者的起点,它们要去共同的终点。
默认冒名顶替者的速度是\(1\)。
询问两个人的最小速度,使得可以安全的抵达终点,不被冒名顶替者拦截。
做法:
先处理出两个起点到所有点的dij。
然后需要找到一条路径,我抵达每个点都比另一个人要快,这条路径的贡献就是这些点的最大速度,这些最大速度取最小
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
const int inf=1e9;
typedef long long ll;
vector<pair<int,int> > g[maxn];
int d[maxn][3];
unsigned long long c[maxn][3];
int vis[maxn];
int C,I,D,n,m;
struct qnode {
int v,w;
qnode (int vv,int ww) {
v=vv;
w=ww;
}
bool operator < (const qnode &r) const {
return w>r.w;
}
};
double ans=1e9;//有一条路径,我抵达每个点都比另一个人要快,这条路径的贡献就是这些点的最大速度,这些最大速度取最小
//计算起点到每个点要多少速度才能抵达
vector<pair<int,int> > tp[maxn];//后继网络
void dij (int s,int f) {
for (int i=1;i<=n;i++) {
vis[i]=0;
d[i][f]=inf;
c[i][f]=0;
}
priority_queue<qnode> q;
d[s][f]=0;
c[s][f]=1;
q.push(qnode(s,d[s][f]));
while (q.size()) {
qnode tt=q.top();
q.pop();
int u=tt.v;
if (vis[u]) continue;
vis[u]=1;
for (pair<int,int> it:g[u]) {
int v=it.first;
int w=it.second;
if (vis[v]) continue;
if (d[u][f]+w<d[v][f]) {
d[v][f]=d[u][f]+w;
c[v][f]=c[u][f];
q.push(qnode(v,d[v][f]));
}
else if (d[u][f]+w==d[v][f]) {
c[v][f]+=c[u][f];
}
}
}
}
int b[maxn],dd[maxn],in[maxn];
double pp[maxn],pd[maxn];
struct qqnode {
int v;
double w;
qqnode (int vv,double ww) {
v=vv;
w=ww;
}
bool operator < (const qqnode &r) const {
return w>r.w;
}
};
void dij1 (int s) {
priority_queue<qqnode> q;
for (int i=1;i<=n;i++) {
vis[i]=0;
pd[i]=inf;
}
q.push(qqnode(s,pp[s]));
pd[s]=pp[s];
while (q.size()) {
qqnode tt=q.top();
q.pop();
int u=tt.v;
double w=tt.w;
if (vis[u]) continue;
vis[u]=1;
for (pair<int,int> it:g[u]) {
int v=it.first;
if (max(pd[u],pp[v])<pd[v]) {
pd[v]=max(pd[u],pp[v]);
q.push(qqnode(v,pd[v]));
}
}
}
}
int main () {
scanf("%d%d",&n,&m);
while (m--) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
g[u].push_back(make_pair(v,w));
g[v].push_back(make_pair(u,w));
}
scanf("%d%d%d",&C,&I,&D);
dij(C,0);
dij(D,1);
dij(I,2);
if (d[D][0]==inf) return printf("-1\n"),0;
if (d[D][2]==inf) return printf("0.000000\n"),0;
if (d[D][2]==0) return printf("-1\n"),0;
for (int i=1;i<=n;i++) {
if (d[i][2]==0) pp[i]=inf;
else pp[i]=1.0*d[i][0]/d[i][2];//计算最快到这个点的速度
}
dij1(C);
if (pd[D]==inf) return printf("-1\n"),0;
printf("%.6f\n",pd[D]);
}