算法导论23(最小生成树)

1.Kruskal算法

#include<iostream> 
#include<algorithm>  
using namespace std;

const int m=9,n=14;

struct Edge  
{  
    int u,v,w;  
};  
  
bool cmp(Edge a,Edge b)  
{  
    return a.w<b.w;  
}  

//并查集
int p[m],r[m];

void MakeSet(int x)    
{    
    p[x]=x;    
    r[x]=0;    
}    
    
int FindSet(int x)    
{    
    return x==p[x]?x:FindSet(p[x]);
}    
    
void Link(int x,int y)    
{    
    if(r[x]>r[y])p[y]=x;    
    else     
    {    
        p[x]=y;    
        if(r[x]==r[y])r[y]++;    
    }    
}    
    
void Union(int x,int y)    
{    
    Link(FindSet(x),FindSet(y));    
}  
  
int MSTKruskal(Edge *e)  
{  
    for(int i=0;i<m;++i)MakeSet(i);  
    sort(e,e+n,cmp);
    int s=0;
    for(int i=0;i<n;++i)  
    {  
        if(FindSet(e[i].u)!=FindSet(e[i].v))  
        {  
            Union(e[i].u,e[i].v);  
            cout<<e[i].u<<' '<<e[i].v<<' '<<e[i].w<<endl;
            s+=e[i].w;
        }  
    }  
    return s;  
}  

//输入
//0 1 4
//0 7 8
//1 2 8
//1 7 11
//2 3 7
//2 5 4
//2 8 2
//3 4 9
//3 5 14
//4 5 10
//5 6 2
//6 7 1
//6 8 6
//7 8 7
//
//输出
//6 7 1
//2 8 2
//5 6 2
//0 1 4
//2 5 4
//2 3 7
//0 7 8
//3 4 9
//37

int main()  
{
    Edge e[n];  
    for(int i=0;i<n;++i)  
    {
        int j,k,l;  
        cin>>j>>k>>l;  
        e[i].u=j;  
        e[i].v=k;  
        e[i].w=l;  
    }    
    cout<<MSTKruskal(e)<<endl;  
    return 0;  
} 


2.Prim算法

#include<iostream> 
#include<vector>
#include<unordered_set>
#include<algorithm>

using namespace std;
const int N=100;
int key[N],pred[N];

struct Node
{
    int v,w;
    Node *next;
    Node(int x,int y):v(x),w(y),next(0){}
};

struct Graph    
{    
    int VNum,ENum;
    Node *Adj[N];    
};    

void createGraph(Graph &G)    
{    
    cin>>G.VNum>>G.ENum;   
    for(int i=0;i<G.VNum;++i)G.Adj[i]=0;  
    for(int i=0;i<G.ENum;++i)    
    {
        int u,v,w;    
        cin>>u>>v>>w;    
        Node *p=new Node(v,w);  
        p->next=G.Adj[u];  
        G.Adj[u]=p;
        p=new Node(u,w);  
        p->next=G.Adj[v];  
        G.Adj[v]=p;
    }    
}      
  
bool cmp(int x,int y)  
{  
    return key[x]>key[y];  
}
  
int MSTPrim(Graph G,int r)  
{
    for(int i=0;i<G.VNum;++i)
    {
        key[i]=INT_MAX;
        pred[i]=-1;
    }
    key[r]=0;
    //最小堆实现最小优先队列Q
    vector<int> Q;
    for(int i=0;i<G.VNum;++i)Q.push_back(i);
    //V-Q
    unordered_set<int> set; 
    while(!Q.empty())  
    {
        make_heap(Q.begin(),Q.end(),cmp);
        int u=Q[0];
        Q.erase(Q.begin());
        set.insert(u);
        for(Node *p=G.Adj[u];p;p=p->next)
        {
            int v=p->v,w=p->w;
            if(set.find(v)==set.end()&&w<key[v])
            {
                key[v]=w;
                pred[v]=u;
            }
        }
    }
    int s=0;
    for(int i=0;i<G.VNum;++i)
    {
        if(pred[i]!=-1)
        {
            cout<<pred[i]<<' '<<i<<' '<<key[i]<<endl;
            s+=key[i];
        }
    }
    return s;  
}  

//输入
//9 14
//0 1 4
//0 7 8
//1 2 8
//1 7 11
//2 3 7
//2 5 4
//2 8 2
//3 4 9
//3 5 14
//4 5 10
//5 6 2
//6 7 1
//6 8 6
//7 8 7
//
//输出
//0 1 4
//1 2 8
//2 3 7
//3 4 9
//2 5 4
//5 6 2
//6 7 1
//2 8 2
//37

int main()  
{      
    Graph G;
    createGraph(G);
    int r=0;
    cout<<MSTPrim(G,r)<<endl;  
    return 0;  
} 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值