我看到这题后感觉可以建立反向图,遍历所有无速度的边,对无速度边起点反图能到达的所有点连接上无速度边终点,速度就是反图中边的速度,长度是无速度边和有速度边之和,以此消掉所有有速度边后跑dij,但是连样例都过不了,很怀疑这种思路的正确性。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 10005;
int n,m,a[N];
int d;
int edge[N][2],leng[N],idx;
bool vis[N],divis[N];
double dis[N];
int last[N];
struct node{
int v,s,l,tag;
};
struct com{
int v;
double dis;
bool operator < (const com &a) const{
return dis>a.dis;
}
};
vector<node> vec[N],g[N];
inline void dfs(int x){
if(vis[x]) return;
int u = edge[x][0],to = edge[x][1];
vis[x] = 1;
for(int i=0;i<g[u].size();i++){
if(g[u][i].tag){
dfs(g[u][i].tag);
continue;
}
int v = g[u][i].v;
vec[v].push_back({to,g[u][i].s,g[u][i].l+leng[x],0});
g[to].push_back({v,g[u][i].s,g[u][i].l+leng[x],0});
}
}
inline void dij(int s){
priority_queue<com> q;
for(int i=0;i<=n;i++){
dis[i] = 1e16;
}
dis[s] = 0;
q.push({s,0});
while(!q.empty()){
int u = q.top().v;
q.pop();
if(divis[u]) continue;
divis[u] = 1;
for(auto ed:vec[u]){
if(ed.tag) continue;
double w = double(ed.l)/ed.s;
//cout<<ed.l<<' '<<ed.s<<endl;
if(dis[ed.v] > dis[u] + w){
dis[ed.v] = dis[u] + w;
last[ed.v] = u;
q.push({ed.v,dis[ed.v]});
}
}
}
}
inline void print(int x){
if(x) print(last[x]);
cout<<x<<" ";
}
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m>>d;
int q1,q2,q3,q4;
for(int i=1;i<=m;i++){
cin>>q1>>q2>>q3>>q4;
if(q3==0 && q1==0){
q3 = 70;
}
if(q3==0){
edge[++idx][0] = q1,edge[++idx][1] = q2;
leng[idx] = q4;
vec[q1].push_back({q2,-1,q4,idx});
g[q2].push_back({q1,-1,q4,idx});
}
else{
vec[q1].push_back({q2,q3,q4,0});
g[q2].push_back({q1,q3,q4,1});
}
}
for(int i=1;i<=idx;i++){
if(!vis[i]) dfs(i);
}
dij(0);
print(d);
return 0;
}