Luogu5905 【模板】Johnson 全源最短路
https://www.luogu.com.cn/problem/P5905
Johnson
将源点设为\(0\),将\(0\)向每个点连一条边权为\(0\)的边
先跑一边\(SPFA\)
再将\(u\rightarrow v\)的一条边的边权增加\(dis[u]-dis[v]\)
从每个点开始跑\(dijkstra\),求出最短路径,对于一条\(s\rightarrow t\)的边,最短路径减去\(dis[s]-dis[t]\),就求出了最短路
C++ Code:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define N 6000005
#define INF 1000000000
#define pr pair<long long,int>
using namespace std;
struct node
{
int x,y,z;
}e[N];
int tot,n,m,head[N],d1[N],d2[N],nxt[N],in[N];
queue<int>q;
priority_queue<pr,vector<pr>,greater<pr> >qq;
bool vis[N];
long long ans=0,dis[N],d[N];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while (ch<'0'||ch>'9')
{
if (ch=='-')
w=-1;
ch=getchar();
}
while ('0'<=ch&&ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline void add(int x,int y,int z)
{
tot++;
d1[tot]=y;
d2[tot]=z;
nxt[tot]=head[x];
head[x]=tot;
}
inline void spfa()
{
for (int i=0;i<=n;i++)
dis[i]=INF;
dis[0]=0;
vis[0]=true;
q.push(0);
while (!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for (int i=head[u];i;i=nxt[i])
{
int v=d1[i];
int cost=d2[i];
if (dis[u]+cost<dis[v])
{
dis[v]=dis[u]+cost;
if (!vis[v])
{
vis[v]=true;
q.push(v);
in[v]++;
if (in[v]==n)
{
puts("-1");
exit(0);
}
}
}
}
}
}
void write(long long ans)
{
if (!ans)
return;
if (ans<0)
putchar('-'),ans=-ans;
write(ans/10);
putchar((char)(ans%10+48));
}
int main()
{
n=read(),m=read();
for (int i=1;i<=m;i++)
{
e[i].x=read(),e[i].y=read(),e[i].z=read();
add(e[i].x,e[i].y,e[i].z);
}
for (int i=1;i<=n;i++)
add(0,i,0);
spfa();
for (int i=1;i<=m;i++)
{
e[i].z+=dis[e[i].x]-dis[e[i].y];
d2[i]+=dis[e[i].x]-dis[e[i].y];
}
for (int i=1;i<=n;i++)
{
ans=0;
for (int j=1;j<=n;j++)
d[j]=INF,vis[j]=false;
d[i]=0;
while (!qq.empty())
qq.pop();
qq.push(make_pair(d[i],i));
while (!qq.empty())
{
int u=qq.top().second;
qq.pop();
if (vis[u])
continue;
vis[u]=true;
for (int i=head[u];i;i=nxt[i])
{
int v=d1[i];
int cost=d2[i];
if (d[u]+cost<d[v])
{
d[v]=d[u]+cost;
qq.push(make_pair(d[v],v));
}
}
}
for (int j=1;j<=n;j++)
if (d[j]==INF)
ans=ans+(long long)j*INF; else
ans=ans+(long long)j*(d[j]-dis[i]+dis[j]);
if (!ans)
putchar('0'); else
write(ans);
putchar('\n');
}
return 0;
}