//可以选择一个中转点
//也就是先正着走到这个点
//然后再从这个点开始反着走
//但是如果已经开始反着走了,那就只可以反着走图
//正着和反着跑,有点奇妙
//学到了
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf=1e18;
const int M=2e5+5;
using pii=pair<int,int>;
//传的参数太多了,不如写两个
int h1[M],ne1[M],e1[M],w1[M],tot1;
int h2[M],ne2[M],e2[M],w2[M],tot2;
void add1(int from,int to,int wi) {
e1[++tot1]=to;
w1[tot1]=wi;
ne1[tot1]=h1[from];
h1[from]=tot1;
}
void add2(int from,int to,int wi) {
e2[++tot2]=to;
w2[tot2]=wi;
ne2[tot2]=h2[from];
h2[from]=tot2;
}
int n,m;
int dis[M][2];
bool vis[M][2];
void dij() {
for(int i=1;i<=n;i++)
dis[i][0]=dis[i][1]=inf;
dis[1][0]=dis[1][1]=0;
priority_queue<pii,vector<pii>,greater<pii>>q;
q.push({dis[1][0],1});
q.push({dis[1][1],-1});
while(!q.empty()) {
auto [st,now]=q.top();
q.pop();
if(now>0&&vis[now][0]==0) {
vis[now][0]=1;
for(int i=h1[now];i;i=ne1[i]) {
int to=e1[i],wi=w1[i];
if(dis[to][0]>st+wi) {
dis[to][0]=st+wi;
q.push({dis[to][0],to});
}
}
for(int i=h2[now];i;i=ne2[i]) {
int to=e2[i],wi=w2[i];
if(dis[to][1]>st+wi) {
dis[to][1]=st+wi;
q.push({dis[to][1],-to});
}
}
}
if(now<0&&vis[-now][1]==0) {
now=abs(now);
vis[now][1]=1;
for(int i=h2[now];i;i=ne2[i]) {
int to=e2[i],wi=w2[i];
if(dis[to][1]>st+wi) {
dis[to][1]=st+wi;
q.push({dis[to][1],-to});
}
}
}
}
}
//从某个点开始反水,然后找到那个最小的距离就可以了
signed main() {
cin>>n>>m;
while(m--) {
int u,v,wi;
cin>>u>>v>>wi;
add1(u,v,wi);
add2(v,u,wi);
}
dij();
for(int i=2;i<=n;i++) {
int ans=min(dis[i][0],dis[i][1]);
if(ans==inf)cout<<-1<<' ';
else cout<<ans<<' ';
}
return 0;
}
标签:now,int,短路,相遇,wi,st,tot2,不同点,dis
From: https://www.cnblogs.com/basicecho/p/16882039.html