P5905 【模板】Johnson 全源最短路
https://www.luogu.com.cn/problem/P5905
#include <bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
int rd() {
int sum=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0') {
sum=sum*10+ch-'0';
ch=getchar();
}
return sum*f;
}
const int inf=(int)(1e9),N=3005;
vector<pair<int,int> >g[N];
int n,m,h[N],cnt[N];
bool vis[N];
queue<int>q;
bool spfa() {
for(int i=0;i<=n;i++) h[i]=inf,vis[i]=0,cnt[i]=0;
q.push(0); h[0]=0;
while(!q.empty()) {
int x=q.front(); q.pop();
vis[x]=0;
for(auto i:g[x]) {
int y=i.first,w=i.second;
if(h[y]>h[x]+w) {
h[y]=h[x]+w;
cnt[y]=cnt[x]+1;
if(cnt[y]>n) {
return 1;
}
if(!vis[y]) vis[y]=1,q.push(y);
}
}
}
return 0;
}
struct node {
int x,d;
node(int xx,int dd) {
x=xx; d=dd;
}
bool operator < (const node &rhs) const {
return d>rhs.d;
}
};
int dis[N];
priority_queue<node>Q;
signed main() {
n=rd(); m=rd();
for(int i=1;i<=m;i++) {
int x=rd(),y=rd(),z=rd();
g[x].pb(make_pair(y,z));
}
for(int i=1;i<=n;i++) g[0].pb(make_pair(i,0));
if(spfa()) {
printf("-1"); return 0;
}
g[0].clear();
// for(int i=1;i<=n;i++) cout<<h[i]<<' ';
for(int i=1;i<=n;i++)
for(auto &j:g[i])
j.second=j.second+h[i]-h[j.first];
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) dis[j]=inf,vis[j]=0;
dis[i]=0; Q.push(node(i,0));
while(!Q.empty()) {
int x=Q.top().x; Q.pop();
if(vis[x]) continue ;
vis[x]=1; //可能若干入边,导致进队若干次,但是只要最小的 dis 去松弛
for(auto i:g[x]) {
int y=i.first,w=i.second;
if(dis[y]>dis[x]+w) {
dis[y]=dis[x]+w;
Q.push(node(y,dis[y]));
}
}
}
int res=0;
for(int j=1;j<=n;j++) {
if(dis[j]>=inf) {
res+=inf*j; continue ;
}
int d=dis[j]-h[i]+h[j];
res+=d*j;
}
printf("%lld\n",res);
}
return 0;
}