Prim算法


內置類型pair介紹

pair的應用

將兩個數據合成一個數據(元組),方便使用。如當一個函數需要返回兩個數據,可以返回pair類型。pair的實現是一個結構體。有兩個成員:first,second。

make_pair函數

template pair make_pair(T1 a, T2 b) { return pair(a, b); }

usage1: std::make_pair(1, 1.1)

靈活的方式,會自動進行類型轉換,T1為int,T2為double

usage2: std::pair<int, float>(1, 1.1);

指定T1,T2類型

使用樣例

pair<int, double> p1;            //使用默認構造函數
pair<int, double> p2(1, 2.4);   //用給定值初始化
pair<int, double> p3(p2);       //使用p2初始化p3

p1.first=1;
p1.second=2.5;
cout<<p1.first<<" "<<p1.second<<endl;

p2=make_pair(1, 1.2);

簡化申明

有時候會覺得使用起來很繁瑣,可以使typedef簡化申明:

typedef pair<string, string> author;
author zuozhe1("Jim", "Green");
author zuozhe2("Jack", "Brown");
string s1="W.Bush";
string s2="George";
author newone;
newone=make_pair(s1, s2);

排序

作為系統內置類型,pair自帶排序能力:先比較第一個參數,如果第一個參數相同再比較第二個參數。你可以使用greater<pair<T1, T2> >less<pair<T1, T2> >來控制排序方式。


朴素Prim復雜度為O(N^2),此Prim算法使用了優先隊列優化,復雜度介於O(eloge)~O(nloge)之間,鼓勵你使用模板題與Kruskal對比計算效率。

一般而言,朴素Prim適用於點少邊多的情況,Kruskal適用於點多邊少的情況。

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int, int> pii;
const int maxn=5e3+5, maxm=4e5+5;
int n, m, head[maxn], nxt[maxm], v[maxm], w[maxm], cnt, dis[maxn];
bool tag[maxn];											//標記點是否被加入MST 
void add(int x, int y, int z) { cnt++, v[cnt]=y, w[cnt]=z, nxt[cnt]=head[x], head[x]=cnt; }
int prim(int s)
{
    memset(dis, 0x7f, sizeof(dis));						//清空dis數組 
    priority_queue<pii, vector<pii>, greater<pii> > Q;	//小根堆 
    int num=1, ans=0;									//num統計加入MST的點的數量,ans為MST邊權和 
    tag[s] = true;
    for(int i=head[s]; i; i=nxt[i])
        if(v[i]!=s)	Q.push(make_pair(w[i], v[i])), dis[v[i]]=min(dis[v[i]], w[i]);
    while(!Q.empty() && num!=n)
    {
        while(!Q.empty() && tag[Q.top().second]) Q.pop();//忽略已加入MST的點 
        if(Q.empty())	break;
        int x=Q.top().second;							//最小dis 
        tag[x]=true, ans+=Q.top().first, num++;			//加入mst 
        Q.pop();
        for(int i=head[x]; i; i = nxt[i])				//使用x松弛與當前MST相連點的dis值
            if(!tag[v[i]] && dis[v[i]]>w[i])		Q.push(make_pair(w[i], v[i])), dis[v[i]]=w[i];
    }
    if (num!=n)	return -1;
    else		return ans;
}

int main(void)
{
    scanf("%d%d", &n, &m);
    for(int i=1, x, y, z; i<=m; i++)					//x, y, z放在for內定義可以省一行空間 
		scanf("%d%d%d", &x, &y, &z), add(x, y, z), add(y, x, z);
    int ans=prim(1);
    if(ans!=-1)	printf("%d\n", ans);
    else		printf("orz\n");
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM