P5905 【模板】Johnson 全源最短路

image

image

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;
}
posted @ 2022-08-05 17:23  FxorG  阅读(36)  评论(0)    收藏  举报