题意
给定一个 N N 个点条边的有向图,有 K K <script type="math/tex" id="MathJax-Element-3">K</script>个标记点,要求从规定的起点按任意顺序经过所有标记点到达规定的终点,问最短的距离是多少。
思路
求出起点和每个标记点作为起点的单源最短路,然后枚举一下经过标记点的顺序记录答案。
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long inf = 1e18;
struct Edge{
int to, next, v;
}e[100001];
int N, M, K, S, T, x, f = 1;
long long ans = inf;
int head[50001], q[11];
long long dis[12][50001];
bool v[11];
void spfa(int s) {
queue<int> que;
int v[50001];
dis[s][q[s]] = 0;
v[q[s]] = 1;
que.push(q[s]);
while (que.size()) {
v[q[s]] = 0;
int x = que.front();
que.pop();
for (int i = head[x]; i; i = e[i].next) {
if (dis[s][x] + e[i].v < dis[s][e[i].to]) {
dis[s][e[i].to] = dis[s][x] + e[i].v;
que.push(e[i].to);
v[e[i].to] = 1;
}
}
}
}
void dfs(int dep, long long sum, int fa) {//枚举顺序
if (dep == K) {
ans = min(sum + dis[fa][T], ans);
return;
}
for (int i = 1; i <= K; i++) {
if (!v[i]) {
v[i]=1;
dfs(dep + 1, sum + dis[fa][q[i]], i);
v[i]=0;
}
}
}
int main() {
memset(dis, 127/2, sizeof(dis));
scanf("%d %d %d %d %d", &N, &M, &K, &S, &T);
for (int i = 1; i <= M; i++) {
scanf("%d %d %d", &x, &e[i].to, &e[i].v);
e[i].next = head[x];
head[x] = i;
}
q[0] = S;
spfa(0);//起点最短路
for (int i = 1; i <= K; i++) {
scanf("%d", &q[i]);
spfa(i);//特殊点最短路
}
dfs(0, 0, 0);
printf("%lld", (ans==inf) ? -1 : ans);
}