二叉樹----二叉樹基本概念
阿新 • • 發佈:2022-03-01
#include <bits/stdc++.h> using namespace std; typedef pair<int, int> PII; const int N = 50010; //車站數目 const int M = 200010; //公路數目 const int INF = 0x3f3f3f3f; int n, m; //車站數目,公路數目 int h[N], e[M], w[M], ne[M], idx; void add(int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } int dist[6][N]; //到每個親戚家的最短距離 int source[6]; //親戚家,0號索引:佳佳的家在車站1,他有五個親戚 bool st[N]; // Dijkstra堆優化版本專用,是否在佇列中 // start:出發點 // dist[]:是全域性變數dist[6][N]的某一個二維,其實是一個一維陣列 // C++的特點,如果陣列做引數傳遞的話,將直接修改原地址的資料 void dijkstra(int start, int dist[]) { dist[start] = 0; memset(st, 0, sizeof st); priority_queue<PII, vector<PII>, greater<PII>> q; q.push({0, start}); while (q.size()) { auto t = q.top(); q.pop(); int u = t.second; if (!st[u]) { st[u] = true; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (dist[j] > dist[u] + w[i]) { dist[j] = dist[u] + w[i]; q.push({dist[j], j}); } } } } } int ans = INF; // step:走的步數 // pre:前序結點 // sum:按此路徑走的總距離和 // 返回值:從佳佳家出發,走完所有親戚家,列舉所有全排列組合中找到的最小距離和 void dfs(int step, int pre, int sum) { //如果完成全排列,那麼返回最短的距離和 if (step == 5 + 1) { ans = min(ans, sum); return; } //預求最小先設最大 //五個親戚家 for (int i = 1; i <= 5; i++) if (!st[i]) { //如果這個親戚沒走過 int u = source[i]; //根據第幾個親戚,找出這家親戚的節點號 st[i] = true; //走他 dfs(step + 1, i, sum + dist[pre][u]); st[i] = false; //回溯 } } int main() { cin >> n >> m; source[0] = 1; // 1號車站是佳佳家,索引是0 for (int i = 1; i <= 5; i++) cin >> source[i]; //五個親戚家 memset(h, -1, sizeof h); //初始化連結串列頭 // m條邊 while (m--) { int a, b, c; cin >> a >> b >> c; add(a, b, c), add(b, a, c); } //計算從任意一點出發,到達其它幾個點的最短路徑 //第一個引數是出發點,第二個引數是個二維陣列,描述到其它任意一個點的距離 memset(dist, 0x3f, sizeof dist); //將二維陣列全部實始化為INF for (int i = 0; i < 6; i++) dijkstra(source[i], dist[i]); // dfs還要用這個st陣列做其它用途,所以,需要再次的清空 memset(st, 0, sizeof st); // 1:準備走第一家親戚,0:前序是佳佳自己家,0:已經走過的距離和是0 dfs(1, 0, 0); printf("%d\n", ans); return 0; }