天天看點

普裡姆算法 Prim

普裡姆算法 Prim

原先一直沒注意這個算法,一直以為迪傑斯特拉可以解決相關問題。後來發現迪傑斯特拉必須要有起點,否則就gg了。而這也是迪傑斯特拉和普裡姆的最大差別。

算法簡述

普裡姆算法的本質是貪心。

常見疑惑的說明:

1.是否可能需要再次更新?

由于已經使用每一個确定最短路長度的節點更新過目前節點,故無需再次更新(因為一個點不能多次到達)。

2.為何把距離起點最近的點作為新的确定最短路長度的節點?

由于該節點是所有尚未确定距離節點中距離起點最短的點,不可能被其它尚未确定距離的節點更新。是以該節點可以作為新的确定最短路長度的節點。

代碼實作

class Prim{
public:
    int prim(int n, vector<vector<int>>& edges) {
        vector<vector<pair<int,int>>> routes(n+1);
        int ans=0,cnt=0;
        for(const auto& edge:edges)
        {
            routes[edge[0]].push_back(make_pair(edge[1],edge[2]));
            routes[edge[1]].push_back(make_pair(edge[0],edge[2]));
        }
        vector<int> used(n+1);
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>> pq;//pq stores {distance,target}

        pq.emplace(0,1);//choose a starting point
        while(!pq.empty()&&cnt<n)
        {
            auto node=pq.top();
            pq.pop();
            int dis=node.first,x=node.second; 
            if(!used[x])
            {
                ans+=dis;
                used[x]=1;
                cnt++;
                for(const auto &route:routes[x])//traverse the edge starting from vertex x
                    pq.emplace(route.second,route.first);
            } 
        }

        if(cnt<n)
            return -1;
        return ans;
    }
};
           
時間複雜度 空間複雜度 補充說明 适用範圍
采用堆 \(O(n+eloge)\) \(O(n+e)\) 頂點數大于邊數(稀疏圖)