题目描述
重庆城里有 n个车站,m条双向公路连接其中的某些车站。
每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他站,但不同的路径需要花费的时间可能不同。
在一条路径上花费的时间等于路径上所有公路需要的时间之和。
佳佳的家在车站 1,他有五个亲戚,分别住在车站 a,b,c,d,e。
过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。
怎样走,才需要最少的时间?
输入格式
第一行:包含两个整数 n,m,分别表示车站数目和公路数目。
第二行:包含五个整数 a,b,c,d,e,分别表示五个亲戚所在车站编号。
以下 m行,每行三个整数 x,y,t,表示公路连接的两个车站编号和时间。
输出格式
输出仅一行,包含一个整数 T,表示最少的总时间。
数据范围
1≤n≤50000,
1≤m≤105,
1<a,b,c,d,e≤n,
1≤x,y≤n,
1≤t≤100
样例
Input
6 6
2 3 4 5 6
1 2 8
2 3 3
3 4 4
4 5 5
5 6 2
1 6 7
Output
21
算法
最短路 + dfs
预处理dis数组,表示出结点1以及结点abcde两两之间的距离。用dfs枚举所有可能的走法。
这个题会把spfa卡掉,所以要用堆优化版的dijkstra。
因为dijkstra和dfs共用st数组,所以在dfs之前要清空st数组(因为这个debug了一会儿。。
时间复杂度
五个结点之间所有可能的走法数量非常小,只考虑dijkstra的复杂度即可。
$O(m \times logm)$
C++ 代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 50010, M = 200010, INF = 0x3f3f3f3f;
int h[N], va[M], ne[M], we[M], idx;
int d[N];
bool st[N];
int n, m, rel[6];
int dis[6][6], res = INF;
void insert(int u, int v, int w) {
va[++idx] = v, we[idx] = w, ne[idx] = h[u], h[u] = idx;
}
void dijkstra(int ps) {
memset(d, 0x3f, sizeof d);
memset(st, 0, sizeof st);
d[ps] = 0;
priority_queue<PII, vector<PII>, greater<PII> > heap;
heap.push({0, ps});
while (!heap.empty()) {
PII t = heap.top();
heap.pop();
int ver = t.second;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i; i = ne[i]) {
int j = va[i], w = we[i];
if (d[j] > d[ver] + w) {
d[j] = d[ver] + w;
heap.push({d[j], j});
}
}
}
}
void dfs(int u, int id, int t) {
if (u == 5) {
res = min(res, t);
return;
}
for (int i = 1; i <= 5; i++)
if (!st[i]) {
st[i] = true;
dfs(u + 1, i, t + dis[id][i]);
st[i] = false;
}
}
int main() {
scanf("%d%d", &n, &m);
rel[0] = 1;
for (int i = 1; i <= 5; i++)
scanf("%d", &rel[i]);
while (m--) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
insert(u, v, w), insert(v, u, w);
}
for (int i = 0; i < 5; i++) {
//spfa(rel[i]);
dijkstra(rel[i]);
for (int j = i + 1; j <= 5; j++)
dis[i][j] = dis[j][i] = d[rel[j]];
}
memset(st, 0, sizeof st);
dfs(0, 0, 0);
printf("%d\n", res);
return 0;
}