图的最小生成树

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;
}
posted @ 2021-12-13 22:32  Lord-Phantom-city  阅读(32)  评论(0)    收藏  举报