很久没做过这么水的E了,发篇题解纪念一下
题目大意
某地区有 N N N 个城镇,编号为 1 到 N N N ,并且由 M M M 条公路连接,编号 1 到 M M M 。
每条公路都是有向的;而且编号为 i ( 1 ≤ i ≤ M ) i(1 \le i \le M) i(1≤i≤M) 的道路将带领你从编号 A i A_i Ai 的城镇到编号为 B i B_i Bi 的城镇去,它的长度为 C i C_i Ci。
现在给你一个长度为 K K K 的正整数序列 E = ( E 1 , E 2 , . . . , E K ) E=(E_1,E_2,...,E_K) E=(E1,E2,...,EK) 且 ∀ i ∈ [ 1 , K ] , E i ∈ [ 1 , M ] \forall i \in [1,K],E_i \in [1,M] ∀i∈[1,K],Ei∈[1,M] 。我们说一条由一些连通的公路组成的路径为“好路”,当且仅当满足以下条件:
- 这条路径的起点为 1 ,终点为 N N N 。
- 按经过顺序组成这条路径的公路的编号组成的序列是 E E E 的子序列。
注意,若序列 S S S 是长度为 L L L 的数列 T T T 的子序列,则 S S S 是数列 T T T 删除任意 i ( i ∈ [ 0 , L ] ) i\ (i\in [0,L]) i (i∈[0,L]) 个元素得到的。
现在你要找到最短的“好路”。如果没有,输出 -1
。
解题思路
枚举城市?显然没有头绪。既然要求最后组成的序列是给定序列的一个子序列,那我们不妨就从给定的序列入手进行DP,这样可以直接规避掉不符合条件的路线。输入给定序列时,输入一次就看一下走这条路径会不会更优,会的话更新一下答案就可以了。
代码示例
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,k,a[200010],b[200010],c[200010],dp[200010];
signed main(){
memset(dp,0x3f,sizeof(dp));
dp[1]=0;
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++){
int x;
cin>>x;
dp[b[x]]=min(dp[b[x]],dp[a[x]]+c[x]);
}
cout<<((dp[n]==0x3f3f3f3f3f3f3f3f)?-1:dp[n])<<endl;
return 0;
}