题目描述
重庆城里有 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
输入样例:
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
输出样例:
21
算法1
使用DFS枚举各种路径的组合可能 然后使用最短路计算各点之间的最短距离。
可优化的点在于 先计算最短路径后,在枚举路径计算最短路径可以直接查表。
但是数据居然卡SPFA ,再次尝试 使用堆优化的dijkstra
时间复杂度
参考文献
C++ 代码
// 11235.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
/*
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
*/
const int N = 50010;
const int M = 1e5 + 10;
typedef pair<int, int> PII;
vector < pair<int, int>> g[N];
int dist[N];
bool st[N];
int n, m;
int ans = 3e8;
int family[7];
int familyCopy[7];
int path[7];
int allDist[7][N];
int spfa(int p)
{
memset(dist, 0x3f, sizeof(dist));
memset(st, 0, sizeof(st));
//p点作为起始 到其他点的最短距离
dist[p] = 0;
queue<int> q;
q.push(p);
st[p] = true;
while (q.size()) {
int t = q.front();
q.pop();
st[t] = false;
for (int i = 0; i < g[t].size(); i++) {
int j = g[t][i].first;
int w = g[t][i].second;
if (dist[j] > dist[t] + w) {
dist[j] = dist[t] + w;
if (!st[j]) {
q.push(j);
st[j] = true;
}
}
}
}
return dist[n];
}
int dfs(int count)
{
if (count == 6) {
int sum = 0;
for (int i = 0; i < 5; i++) {
int from = path[i];
int to = path[i + 1];
int idx = -1;
for (int j = 0; j < 6; j++) {
if (from == familyCopy[j]){
idx = j; break;
}
}
sum += allDist[idx][to];
}
return sum;
}
for (int i = 1; i <= 5; i++) {
if (family[i] != 0) {
path[count] = family[i];family[i] = 0;count++;
ans = min (ans,dfs(count));
count--;family[i] = path[count];path[count] = 0;
}
}
return ans;
}
int dij(int p)
{
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
dist[p] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({ 0, p });
while (heap.size()) {
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = 0; i < g[ver].size(); i++) {
int j = g[ver][i].first;
int w = g[ver][i].second;
if (dist[j] > dist[ver] + w) {
dist[j] = dist[ver] + w;
heap.push({ dist[j],j });
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
void useDIJ() {
for (int i = 0; i < 6; i++) {
dij(family[i]);
memcpy(allDist[i], dist, sizeof(dist));
}
path[0] = 1;
cout << dfs(1) << endl;
}
void useSPFA() {
for (int i = 0; i < 6; i++) {
spfa(family[i]);
memcpy(allDist[i], dist, sizeof(dist));
}
path[0] = 1;
cout << dfs(1) << endl;
}
int main()
{
cin >> n >> m;
family[0] = 1;
for (int i = 1; i <= 5; i++) {
cin >> family[i];
}
memcpy(familyCopy, family, sizeof(family));
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
g[a].push_back({ b,c });
g[b].push_back({ a,c });
}
useDIJ();
//useSPFA();
return 0;
}