请给出以下问题的完整C++代码实现:给定n个城市(从0到n-1),3元组[A, B, C]表示城市A和城市B之间存在道路,且成本为C。计算从0号城市出发,旅行完每个城市一遍,最后回到0号城市的最小成本与路径。如果不存在最优方案,输出-1. 【输入形式】 第一行有两个数n、m表示n个城市,m条边。 接下来的m行均为空格隔开的三个整数A B C,表示城市A和B之间的成本为C 【输出形式】 最小成本 最小成本对应的路径
时间: 2023-11-27 16:49:44 浏览: 61
以下是完整的C++代码实现,使用了Dijkstra算法和回溯法:
```c++
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int MAXN = 15;
const int INF = 0x3f3f3f3f;
struct Edge {
int to, cost;
Edge(int to, int cost) : to(to), cost(cost) {}
};
vector<Edge> G[MAXN]; // 邻接表存图
int dist[MAXN][1 << MAXN]; // dist[i][S]表示从0出发,经过集合S中的城市,最后到达i的最小成本
int n, m;
bool vis[MAXN];
void dijkstra(int s) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
memset(vis, false, sizeof(vis));
memset(dist, INF, sizeof(dist));
dist[s][1 << s] = 0;
q.push(make_pair(0, s << n | 1 << s));
while (!q.empty()) {
int d = q.top().first;
int v = q.top().second >> n, S = q.top().second & ((1 << n) - 1);
q.pop();
if (vis[v][S]) continue;
vis[v][S] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i].to, c = G[v][i].cost;
if (S & (1 << u)) continue;
if (dist[u][S | (1 << u)] > dist[v][S] + c) {
dist[u][S | (1 << u)] = dist[v][S] + c;
q.push(make_pair(dist[u][S | (1 << u)], u << n | S | (1 << u)));
}
}
}
}
int ans = INF, path[MAXN], cnt;
void dfs(int u, int S, int cost, int depth) {
if (cost >= ans) return;
path[depth] = u;
if (depth == n - 1) {
if (G[u][0].to == 0) { // 回到0号城市
ans = cost + G[u][0].cost;
cnt = depth;
return;
}
}
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i].to, c = G[u][i].cost;
if ((S & (1 << v)) || depth == n - 1) continue; // 已经访问过或者已经走完所有城市
dfs(v, S | (1 << v), cost + c, depth + 1);
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v, c;
cin >> u >> v >> c;
G[u].push_back(Edge(v, c));
G[v].push_back(Edge(u, c));
}
dijkstra(0);
int minCost = INF, S = 0;
for (int i = 0; i < (1 << n); i++) { // 枚举所有的集合
if (dist[0][i] >= INF) continue;
int cost = dist[0][i];
for (int j = 0; j < n; j++) {
if (i & (1 << j)) cost += G[j][0].cost; // 回到0号城市的成本
}
if (cost < minCost) {
minCost = cost;
S = i;
}
}
if (minCost == INF) cout << -1 << endl;
else {
cout << minCost << endl;
dfs(0, S, 0, 0);
cout << "0 ";
for (int i = 0; i < cnt; i++) cout << path[i] << " ";
cout << "0" << endl;
}
return 0;
}
```
首先我们使用Dijkstra算法求出从0出发,到达所有城市的最短路径。dist[i][S]表示从0出发,经过集合S中的城市,最后到达i的最小成本。对于每个集合S,我们只需要枚举所有的子集,然后计算回到0号城市的成本,取最小值即可。
然后我们使用回溯法,从0号城市开始,依次遍历所有城市,找到一条经过所有城市(除了0号城市)的路径,并且最后回到0号城市的成本最小的路径。我们用path数组存储路径,cnt表示路径长度。
阅读全文