UPC-2020.2.25セッション25:質問M-香港レポーター(最短パス+復元パス)-SPFA / Dijkstraアルゴリズム

私のハンサムな光学ディレクターは、この問題のパスの復元はバックパックのパスの復元と同じであると私に言いました。

タイトル説明

ご存知のように、香港の記者は誰よりも速く走ります。実際には秘密があります。
まず、最短経路を走りますが、最短経路が多く、他の記者も最短経路を知っています。香港の記者も、各都市で黒い縁の眼鏡をかけている人の数を数えました。黒縁の眼鏡をかけている人の割合は、他の記者よりも語彙の順序が大きいため、この記者は言葉では言い表せないほどの力で伸び、語彙の順序が低い記者よりも速く走ります。
高齢者は毎日すべてを知っています。香港の記者を見つけて教えることができるように、香港の記者が移動した総距離と、市内で黒い縁の眼鏡をかけている人の数の順序を教えてください。いくつかの人生経験。
便宜上、始点を1、終点をnとします。
言葉では言い表せないほどの力で、黒い縁の眼鏡をかけている人の数は都市によって異なります。最初の行を
入力し
ます。2つの整数nとmは、n個の都市があり、都市間にm個の有向エッジがあることを示します。
2番目の行である数字nは、各都市で黒縁の眼鏡をかけているbiの人数を表します。
次のm行では、各行に3つの非負の整数ui、vi、wiが含まれ、開始点、終了点、およびを表します。有向エッジの距離。
出力
最初の行で、負でない整数は、香港の記者が移動した合計距離を表します。
2行目では、負でない整数の数が、香港の記者が通過した都市で黒い眼鏡をかけている人の数のシーケンスを表しています。

サンプル入力コピー

8 9
1 2 3 4 5 6 7 8
1 2 2
2 3 3
3 8 3
1 4 3
4 5 2
5 8 1
1 6 1
6 7 2
7 8 3

サンプル出力コピー

6
1 4 5 8

促す

2≤n≤2×105、1≤m≤4×105、1≤w≤1×109の場合、始点から終点までの最短経路が少なくとも1つあります。

トピック分析

2e5ポイントでは、ソリューション1のダイクストラのキュー最適化を使用できます。ソリューション2のSPFAに
は、復元パスの最小辞書式順序が必要です。解の数を見つけるため
ナップサック問題は、最小の辞書式順序を復元するためのパスもあると思いました
当時は、最後のナップサックから前方にトラバースするために使用されていました。
この問題では、保存されているエッジ情報を逆にして、Nから1への最短経路を見つけることができます。

パスを復元したいので、nの前のポイントを表す新しい配列pre [n]を設定します。

もし
DIST [V]> DIST [U] + W(U、V)
次に
DIST [V] = DIST [U] + W(U、V);
もし
DIST [V] == DIST [U] + W(uと、v)
このとき、pre [v]の点の重みがuの点の重みよりも大きい場合、
pre [v] = uになります。

コード1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define  gold_m main
#define re register
#define Accept return 0;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//const int inf =0x3f3f3f3f;
const ll  inf =0x3f3f3f3f3f3f3f;
const int maxn=1e6+5;
const int mod = 1e9+7;
const int N = 666;
const long double PI=3.1415926535897932384626433832795;
//const long double e=2.71828182845904523536028747135266;
typedef pair<ll,ll>PII;
inline ll read() {
    
    
	ll  x=0;
	bool f=0;
	char ch=getchar();
	while (ch<'0'||'9'<ch)	f|=ch=='-', ch=getchar();
	while ('0'<=ch && ch<='9')
		x=x*10+ch-'0',ch=getchar();
	return f?-x:x;
}
//priority_queue<int,vector<int>, greater<int> >heap;
//stack<int>st;
ll  n,m,a[maxn],cnt,head[maxn],dist[maxn],st[maxn],pre[maxn],path[maxn];
struct wmy {
    
    
	ll u,v,w,next;
} e[maxn];
void add(ll u ,ll v,ll w) {
    
    
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].next=head[u];
	head[u]=cnt++;
}
ll  Dijkstra() {
    
    
	priority_queue<PII,vector<PII>,greater<PII>>heap;
	dist[n]=0;
	heap.push({
    
    0,n});
	while(!heap.empty()) {
    
    
		auto fr=heap.top();
		heap.pop();
		ll u=fr.second;
		ll w=fr.first;
		if(st[u]) continue;
		st[u]=1;
		for(int j=head[u]; j!=-1; j=e[j].next) {
    
    
			ll t= e[j].v;
			if(dist[t]>w+e[j].w||(dist[t]==e[j].w+dist[u]&&a[u]<=a[pre[t]])) {
    
    
				dist[e[j].v]=w+e[j].w;
				pre[e[j].v]=u;
				heap.push({
    
    dist[e[j].v],e[j].v});
			}
		}
	}
	
return dist[1];

}
int   gold_m() {
    
    
	memset(head,-1,sizeof(head));
	memset(pre,-1,sizeof(pre));
	n=read();
	m=read();
	for(int i=1 ; i<=n ; i++) a[i]=read(),dist[i]=inf;
	for(int i=1 ; i<=m; i++) {
    
    
		ll u,v,w;
		u=read();
		v=read();
		w=read();
		add(v,u,w);
	}
	cout<<Dijkstra()<<endl<<a[1]<<" ";
	int i=1;
	while(i!=n) {
    
    
		printf("%d ",a[pre[i]]);
		i=pre[i];
	}
	Accept;
}
/*
8 9
1 2 3 4 5 6 7 8
1 2 2
2 3 3
3 8 3
1 4 3
4 5 2
5 8 1
1 6 1
6 7 2
7 8 3
*/

コード2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define  gold_m main
#define re register
#define Accept return 0;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//const int inf =0x3f3f3f3f;
const ll  inf =0x3f3f3f3f3f3f3f;
const int maxn=2e6+15;
const int mod = 1e9+7;
const int N = 666;
const long double PI=3.1415926535897932384626433832795;
//const long double e=2.71828182845904523536028747135266;
typedef pair<ll,ll>PII;
inline ll read() {
    
    
	ll  x=0;
	bool f=0;
	char ch=getchar();
	while (ch<'0'||'9'<ch)	f|=ch=='-', ch=getchar();
	while ('0'<=ch && ch<='9')
		x=x*10+ch-'0',ch=getchar();
	return f?-x:x;
}
//priority_queue<int,vector<int>, greater<int> >heap;
//stack<int>st;
ll  n,m,a[maxn],cnt,head[maxn],dist[maxn],st[maxn],pre[maxn],path[maxn];
struct wmy {
    
    
	ll u,v,w,next;
} e[maxn];
bool cmp(wmy x,wmy y) {
    
    
	if(x.u!=y.u) return x.u<y.u;
	else return a[x.v]>a[y.v];
}
void add(ll u ,ll v,ll w) {
    
    
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].next=head[u];
	head[u]=cnt++;
}
priority_queue<PII,vector<PII>,greater<PII>>heap;
void spfa() {
    
    
	for(int i=1 ; i<=n; i++) dist[i]=inf;
	dist[n]=0;
	st[n]=1;
//	pre[n]=n;
	queue<ll>q;
	q.push(n);
	while(!q.empty()) {
    
    
		ll u=q.front();
		q.pop();
		st[u]=0;
		for(int i=head[u]; i!=-1; i=e[i].next) {
    
    
			ll t=e[i].v;
			if(dist[t]>e[i].w+dist[u]||(dist[t]==e[i].w+dist[u]&&a[u]<=a[pre[t]])) {
    
    
				dist[t]=e[i].w+dist[u];
				pre[t]=u;
				if(st[t]==0) {
    
    
					st[t]=1;
					q.push(t);
				}
			}
		}
	}
}

int   gold_m() {
    
    
	memset(head,-1,sizeof(head));
//	memset(pre,-1,sizeof(pre));
	scanf("%lld%lld",&n,&m);
	for(ll i=1 ; i<=n ; i++)scanf("%lld",&a[i]);

	for(int i=1 ; i<=m; i++) {
    
    
		ll u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		add(v,u,w);
	}
	spfa();
	printf("%lld\n%lld ",dist[1],a[1]);
	int i=1;
	while(i!=n) {
    
    
		printf("%d ",a[pre[i]]);
		i=pre[i];
	}
	Accept;
}
/*
8 9
1 2 3 4 5 6 7 8
1 2 2
2 3 3
3 8 3
1 4 3
4 5 2
5 8 1
1 6 1
6 7 2
7 8 3


*/

おすすめ

転載: blog.csdn.net/wmy0536/article/details/104494470