开两个dist数组,使用两次spfa,一次以s为起点,一次以t为起点,然后枚举所有边,出边为a终边为b则最小值为s到a+b到t,即使用魔法消除这条路的通过时间,取最小值,如果等于最小值则编号小的优先
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int N = 1e4+10,M = 10*N;
typedef long long ll;
int dist[N],w[M],e[M],ne[M],idx,h[N],diss[N];
bool st[N];
int n,m,s,t;
ll minx=0x3f3f3f3f;
vector<int>lj[N];
inline void add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
struct edge{
int a,b,c;
}edges[M];
void dijkstral(int c,int a[]){
for(int i=1;i<=n;i++)a[i]=0x3f3f3f3f;
memset(st,0,sizeof st);
st[c]=1;
queue<int>p;
p.push(c);
st[c]=1;
a[c]=0;
while(!p.empty()){
int u=p.front();
st[u]=1;
p.pop();
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(a[j]>a[u]+w[i]){
lj[j].clear();
lj[j].push_back(u);
a[j]=a[u]+w[i];
if(!st[j]){
p.push(j);
st[j]=1;
}
} else if(a[j]==a[u]+w[i]) lj[j].push_back(u);
}
}
}
int main(){
memset(h,-1,sizeof h);
scanf("%d %d %d %d",&n,&s,&t,&m);
for(int i=0;i<m;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
add(a,b,c),add(b,a,c);
edges[i*2]={a,b,c};
edges[i*2+1]={b,a,c};
}
dijkstral(s,dist);
dijkstral(t,diss);
int pos;
for(int i=0;i<m*2;i++)
{
int a=edges[i].a,b=edges[i].b;
if(dist[a]+diss[b]<minx)
{
minx= dist[a]+diss[b];
pos=a;
} else if(dist[a]+diss[b]==minx)pos=min(pos,a);
}
cout<<minx<<" "<<pos;
}