因为题目有的条件,所以可能有些同学就选择了跑多次最短路来解题。但这题其实可以通过简单的构造,一次最短路解决。

只需要加一个源点0,在源点和p中每个点之间连一条权值为0的边,然后跑一次以0为起点的单源最短路。

const int INF = 0x3f3f3f3f;

class Solution {
public:
    /**
     * 
     * @param niuniu int整型vector 牛牛占领的p个星球的编号
     * @param niumei int整型vector 牛妹占领的q个星球的编号
     * @param path int整型vector<vector<>> m条隧道,每条隧道有三个数分别是ui,vi,wi。ui,vi分别是隧道的两边星球的编号,wi是它们之间的距离
     * @param nn int整型 星球个数n
     * @return int整型
     */
    int Length(vector<int>& niuniu, vector<int>& niumei, vector<vector<int> >& path, int nn) {
        vector<vector<pair<int, int>>> adj(nn + 1);
        for (int i : niuniu)
            adj[0].emplace_back(i, 0);
        for (auto v : path) {
            adj[v[0]].emplace_back(v[1], v[2]);
            adj[v[1]].emplace_back(v[0], v[2]);
        }
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
        pq.push({0, 0});
        vector<bool> vis(nn + 1);
        vector<int> dist(nn + 1, INF);
        dist[0] = 0;
        while (!pq.empty()) {
            pair<int, int> top = pq.top();
            pq.pop();
            int c = top.first, u = top.second;
            if (vis[u])
                continue;
            vis[u] = true;
            for (pair<int, int> nxt : adj[u]) {
                int v = nxt.first, w = nxt.second;
                if (dist[u] + w < dist[v]) {
                    dist[v] = dist[u] + w;
                    pq.push({dist[v], v});
                }
            }
        }
        int ans = INF;
        for (int i : niumei)
            ans = min(ans, dist[i]);
        if (ans == INF)
            return -1;
        return ans;
    }
};