最小生成树Prim算法Kruskal算法

Prim算法采用与Dijkstra、Bellamn-Ford算法一样的“蓝白点”思想;白点代表已经进入最小生成树的点,蓝点代表未进入最小生成树的点。

算法分析 & 思想讲解:

Prim算法每次都将一个蓝点 U 变成白点,并且此蓝点 U 与白点相连的最小边权还是当前所有蓝点中最小的。这样就相当于向生成树中添加了n-1次最小的边,最后得到的一定是最小生成树。

我们通过对下图最小生成树的求解模拟来理解上面的思想。蓝点和虚线代表未进入最小生成树的点、边;白点和实线代表已进入最小生成树的点、边。
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;

int s[1500][1500],n,distan[1500];
bool visit[1500];
const int maxn=0x7fffffff;

int main()
{
    cin>>n;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
                cin>>s[i][j];
    memset(distan,0x7f,sizeof(distan));
    distan[1]=0;
    int kk=0;
    for(int i=1;i<=n;++i)
    {    
        kk=0;
        for(int j=1;j<=n;++j)
            if(!visit[j]&&distan[j]<distan[kk])
                kk=j;
        visit[kk]=true;
        for(int j=1;j<=n;++j)
        {
            if(!visit[j]&&s[kk][j]<distan[j])
                distan[j]=s[kk][j];
        }
    }
    int ans=0;
    for(int i=1;i<=n;++i)
        ans+=distan[i];
    cout<<ans;
    return 0;
}
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;

struct node
{
    int a,b,dis;
}s[1500];

int sum=1,n,fa[1500];

bool cmp(node a,node b)
{
    return a.dis<b.dis;
}

int find(int son)
{
    if(fa[son]!=son)
        fa[son]=find(fa[son]);
    return fa[son];
}

int main()
{
    int ans=0;
    cin>>n;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            {
                s[sum].a=i;
                s[sum].b=j;
                cin>>s[sum++].dis;
            }
    sort(s+1,s+sum,cmp);
    int k=0;
    for(int i=1;i<=n;++i)
    {
            int r1=find(s[i].a);
            int r2=find(s[i].b);
        if(find(s[i].a)!=find(s[i].b))
        {
            fa[r2]=r1;
            ans+=s[i].dis;
            k++;
        }
        if(k==n-1)
            break;
    }
    cout<<ans;
    return 0;
}

 

posted @ 2017-04-13 17:48  Grary  阅读(225)  评论(0编辑  收藏  举报
博客园 首页 私信博主 编辑 关注 管理 新世界