Johnson最短路板子
我们知道johnson最常见的做法是 spfa+dijkstra
我们先有spfa板子:
bool spfa(int st){ queue<int>q; memset(h,63,sizeof h); h[st]=0; vis[st]=1; q.push(st); while(!q.empty()){ int u=q.front();q.pop(); vis[u]=0; for(int e=head[u];e;e=edge[e].next){//默认使用邻接表存边 int v=edge[e].to; if(h[v]>h[u]+edge[e].dis){ h[v]=h[u]+edge[e].dis; if(!vis[v]){ vis[v]=1; q.push(v); if(++t[v]==n+1)return false;//负环 } } } } return true; }
而后是STL 优先队列(在这里我弄成了小根堆)优化dijkstra
struct node{ ll dis;int id; bool operator <(const node&a)const{ return dis>a.dis; } node(ll d,int x){ dis=d,id=x; } }; void dijkstra(int st){ memset(vis,0,sizeof vis); for(int i=1;i<=n;i++)dis[i]=INF; dis[st]=0; priority_queue<node>q; q.push(node(0,st)); while(!q.empty()){ int u=q.top().id;q.pop(); if(vis[u])continue; vis[u]=1; for(int e=head[u];e;e=edge[e].next){ int v=edge[e].to; if(dis[v]>dis[u]+edge[e].dis){ dis[v]=dis[u]+edge[e].dis; if(!vis[v])q.push(node(dis[v],v)); } } } }
Johnson题目参考 洛谷P5905
//johnson最短路算法 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 5005; const ll INF = 1e9; struct Edge{ int next,to; ll dis; }edge[2*N]; struct node{ ll dis;int id; bool operator <(const node&a)const{ return dis>a.dis; } node(ll d,int x){ dis=d,id=x; } }; int n,m,tot; int head[N],t[N]; ll dis[N],h[N]; bool vis[N]; void add_edge(int from,int to,int dis){ edge[++tot].next=head[from]; edge[tot].to=to; edge[tot].dis=dis; head[from]=tot; } bool spfa(int st){ queue<int>q; memset(h,63,sizeof h); h[st]=0; vis[st]=1; q.push(st); while(!q.empty()){ int u=q.front();q.pop(); vis[u]=0; for(int e=head[u];e;e=edge[e].next){ int v=edge[e].to; if(h[v]>h[u]+edge[e].dis){ h[v]=h[u]+edge[e].dis; if(!vis[v]){ vis[v]=1; q.push(v); if(++t[v]==n+1)return false; } } } } return true; } void dijkstra(int st){ memset(vis,0,sizeof vis); for(int i=1;i<=n;i++)dis[i]=INF; dis[st]=0; priority_queue<node>q; q.push(node(0,st)); while(!q.empty()){ int u=q.top().id;q.pop(); if(vis[u])continue; vis[u]=1; for(int e=head[u];e;e=edge[e].next){ int v=edge[e].to; if(dis[v]>dis[u]+edge[e].dis){ dis[v]=dis[u]+edge[e].dis; if(!vis[v])q.push(node(dis[v],v)); } } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v;ll w; scanf("%d%d%lld",&u,&v,&w); add_edge(u,v,w); } for(int i=1;i<=n;i++)add_edge(0,i,0); if(!spfa(0)){ printf("-1"); return 0; } for(int u=1;u<=n;u++){ for(int e=head[u];e;e=edge[e].next){ edge[e].dis+=h[u]-h[edge[e].to]; } } for(int u=1;u<=n;u++){ dijkstra(u); ll ans=0; for(ll v=1;v<=n;v++){ if(dis[v]==INF)ans+=v*INF; else ans+=v*(dis[v]+h[v]-h[u]); } printf("%lld\n",ans); } return 0; }