一开始很容易想到求出每个路径再去匹配子序列,会发现复杂度太过高了。

然而,我们很容易想到严格按照 ee 数组顺序处理边,这样就保证了子序列。如此,很容易就可以想到 dp[v]=min(dp[v],dp[u]+w)dp[v] = min(dp[v], dp[u] + w) 了,注意转移前先要看 dp[u]dp[u] 是不是极大值,这样转移才有意义。注意 dp[1]=0dp[1] = 0

这样:如果 dp[u]dp[u] 是没有通过子序列到来的,自然就不符合我们的要求,不需要更新;同时,也确保了子序列和起点开始两个要求。最终,看 dp[n]dp[n] 是不是极大值,处理输出即可。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int T = 1;
const int N = 2e5 + 10;
const int INF = 1e16;

int n, m, k;
int a[N], b[N], c[N];
int e[N];
int dp[N];

void Solve() {
	cin >> n >> m >> k;
	for (int i = 1; i <= m; i++) {
		cin >> a[i] >> b[i] >> c[i];
	}
	for (int i = 1; i <= k; i++) {
		cin >> e[i];
	}

	fill(dp, dp + n + 1, INF);
	dp[1] = 0;
	for (int i = 1; i <= k; i++) {
		int u = a[e[i]], v = b[e[i]], w = c[e[i]];
		if (dp[u] != INF) dp[v] = min(dp[v], dp[u] + w);
	}
	cout << (dp[n] == INF ? -1 : dp[n]);
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	while (T--) {
		Solve();
	}
	return 0;
}

2 条评论

  • @ 2026-8-31 3:49:59

    这个码风让人觉得好难

    • @ 2026-8-31 3:48:53

      这题简单这个码风

      • 1