1 条题解

  • 0
    @ 2026-8-30 11:45:41

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

    然而,我们很容易想到严格按照 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;
    }
    
    • 1

    信息

    ID
    2841
    时间
    2000ms
    内存
    1024MiB
    难度
    提高
    标签
    递交数
    1
    已通过
    1
    上传者