1. 程式人生 > 遊戲 >Epic本週喜加一更新 免費領取《城市:天際線》

Epic本週喜加一更新 免費領取《城市:天際線》

題目傳送門

#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;
}