1. 程式人生 > 其它 >圖的最小生成樹

圖的最小生成樹

Prim演算法

核心思想:貪心的將一個又一個點加入集合,而加入的每個點都儘可能使邊權最小,這樣可以使用STL的priority_queue來維護。

struct edge{int to,cost;};//to表示邊的終點,cost表示權值
typedef pair<int,int> P;//P.first表示已有點集到P.second這個點的邊權最小值
priority_queue <P,vector<P>,greater<P> >que;//用於儲存最小邊權值的優先佇列
bool visited[MAX_V];//查詢點是否被訪問
vector<edge> G[MAX_V];
int V;//頂點數

int Prim()
{
    for(int i=0;i<V;i++)
    {
        visited[i]=false;
    }
    int res=0;
    que.push(0,0);
    for(int i=1;i<=V;i++)
    {
        while(true)
        {
            P p=que.top();
            if(!visited[p.second])
            {
                res=res+p.first;
                for(int j=0;j<G[p.second].size();j++)
                {
                    que.push(P(G[p.second].cost,P(G[p.second].to)));
                }
                break;
            }
        }
    }
    return res;
}

Kruskal演算法

核心思想:把邊的權值從小到大排一遍,一條一條加入圖中,不產生圈即為有效。為了簡化,可以用並查集判斷是否構成圈。

struct edge{ int u,v,cost};//u為邊的起點,v為邊的終點,cost為邊的權值
bool cmp(const edge& e1,const edge & e2)
{
    return e1.cost < e2.cost;
}
edge es[MAX_E];//儲存所有的邊
int V,E;//頂點數和邊數
//init,unite,same函式均為並查集的函式,請跳轉至並查集部分
int Kruskal()
{
    sort(es,es+E,cmp);
    init(V);
    int res=0;
    for(int i=0;i<E;i++)
    {
        edge e=es[i];
        if(!same(e.u,e.v))
        {
            unite(e.u,e.v);
            res=res+e.cost;
        }
    }
    return res;
}