RT.
我发现w很小,所以在从终点往起点推的时候只要路程大于起点到这个点经过的边权最大值,就可以不跑了。其余的跑dij,以终点为源点,生命值为准的单源最短路。再用一个bfs预处理以起点为源点的单源路径边权最小的最大值就行。但是可能是我一些细节的问题,我在#14WA了,显示的是wrong answer Too long on line 2.(答案没有求到,是min的初值),所以我在sub3的情况特判了一下,缝合了一开始错误但是能过sub1,3的dij,就AC了……
代码(赛时代码,很丑):
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,pair<int,int> >
#define PIII pair<int,int>
#define x first
#define y second
const int N=4e4+10;
int ne[N*2],e[N*2],h[N*2],idx,w[N*2];
void add(int a,int b,int c){
e[++idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx;
}
int n,m,t,s;
int dis[N][200],dism[N*2],vis[N][200];
bool go[N*2];
int dsa[N*2],viss[N*2],dit[N*2];
int diss[N];
void dij(){
priority_queue<PIII,vector<PIII>,greater<PIII> > qu;
memset(dsa,0x3f,sizeof(dsa));
memset(dit,0x3f,sizeof(dit));
dsa[t]=0,qu.push({0,t});
while(!qu.empty()){
PIII now=qu.top();qu.pop();
if(viss[now.y]) continue;
viss[now.y]=1;
dit[now.y]=0;
for(int i=h[now.y];i;i=ne[i]){
int j=e[i];
if(dit[j]>0){
if(dsa[j]>max(dsa[now.y],w[i])){
dsa[j]=max(dsa[now.y],w[i]);
qu.push({dsa[j],j});
}
}
}
}
}
void aa(){
priority_queue<PII,vector<PII>,greater<PII> > qu;
memset(dis,0x3f,sizeof(dis));
dis[s][0]=0;qu.push({0,{0,s}});
go[s]=1;
while(!qu.empty()){
PII now=qu.top();
qu.pop();
if(vis[now.y.y][now.y.x]) continue;
vis[now.y.y][now.y.x]=1;
go[now.y.y]=1;
if(now.y.x>dsa[now.y.y]) continue;
for(int i=h[now.y.y];i;i=ne[i]){
int j=e[i];
if(dis[j][now.y.x+1]>dis[now.y.y][now.y.x]+(w[i]/(now.y.x+1))){
dis[j][now.y.x+1]=dis[now.y.y][now.y.x]+(w[i]/(now.y.x+1));
qu.push({dis[j][now.y.x+1],{now.y.x+1,j}});
}
}
}
}
void solve(){
cin>>n>>m>>t>>s;
bool bo=0;
for(int i=1;i<=m;i++){
int a,b,c;cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
if(c>1) bo=1;
}
if(!bo){
priority_queue<PIII,vector<PIII>,greater<PIII> > qu;
memset(diss,0x3f,sizeof(diss));
diss[s]=0,qu.push({0,s}),dism[s]=0;
while(!qu.empty()){
PIII now=qu.top();qu.pop();
if(viss[now.y]) continue;
viss[now.y]=1;
for(int i=h[now.y];i;i=ne[i]){
int j=e[i];
if(diss[j]>(w[i]/(dism[now.y]+1))+diss[now.y]){
diss[j]=(w[i]/(dism[now.y]+1)+diss[now.y]),dism[j]=dism[now.y]+1;
qu.push({diss[j],j});
}
else if(diss[j]==(w[i]/(dism[now.y]+1))+diss[now.y]){
if(dism[now.y]+1>dism[j]){
dism[j]=dism[now.y]+1;
}
}
}
}
cout<<diss[t];
return ;
}
dij();
aa();
int minn=1000000000000000000;
for(int i=1;i<=105;i++){
minn=min(minn,dis[t][i]);
}
for(int i=1;i<=n;i++){
if(go[i]){
minn=min(minn,dis[i][dsa[i]]);
}
}
cout<<minn;
}
signed main(){
solve();
return 0;
}