最小生成树算法

    最小生成树算法我只知道两种:Prim和Kruscal。

    Prim算法跟Dijkstra算法一样,属于典型的贪心算法(即从局部最优解得到全局最优解)。

    下面是Prim算法用于以邻接矩阵保存的图的情况。

#define N 1000

int edge[N][N],closedge[N],n;
bool vis[N];
void prim(int s)
{
    int i,j,k;
    for(i=1;i<=n;i++)
        closedge[i]=edge[s][i];
    memset(vis,0,sizeof(vis));
    vis[s]=true;
    for(j=1;j<=n-1;j++)
    {
        k=1;
        while(vis[k])k++;
        int beg=k;
        for(i=k+1;i<=n;i++)
            if(!vis[i]&&closedge[i]<closedge[k])
                k=i;
        vis[k]=true;
        for(i=beg;i<=n;i++)
            if(!vis[i]&&edge[k][i]<closedge[i])
                closedge[i]=edge[k][i];
    }
}

    下面是Prim算法用于以静态邻接表保存的图的情况。

#define N 1000
#define Inf 9999999
struct Edge
{
    int to,w,next;
}e[100000];
int pp[N],n,closedge[N];
bool vis[N];

void prim(int s)
{
    int i,j,k;
    for(i=1;i<=n;i++)
        closedge[i]=Inf;
    closedge[s]=0;
    memset(vis,0,sizeof(vis));
    for(j=1;j<=n;j++)
    {
        k=1;
        while(vis[k])k++;
        for(i=k+1;i<=n;i++)
            if(!vis[i]&&closedge[i]<closedge[k])
                k=i;
        vis[k]=true;
        for(i=pp[k];i!=-1;i=e[i].next)
            if(!vis[e[i].to]&&e[i].w<closedge[e[i].to])
                closedge[e[i].to]=e[i].w;
    }
}
    同样的,Prim算法可以用优先队列来优化。

#define N 1000
#define Inf 9999999
struct Edge
{
    int to,w,next;
}e[100000];
int ec,pp[N],closedge[N],n;
bool vis[N];
struct Node
{
    int u,d;
    bool operator<(const struct Node a)const
    {
        return d>a.d;
    }
}t1;

void prim(int s)
{
    int i,j,k;
    priority_queue<struct Node>que;
    for(i=1;i<=n;i++)
        closedge[i]=Inf;
    memset(vis,0,sizeof(vis));
    closedge[s]=0;
    t1.d=0;
    t1.u=s;
    que.push(t1);
    while(!que.empty())
    {
        t1=que.top();
        que.pop();
        k=t1.u;
        if(vis[k])continue;
        vis[k]=true;
        for(i=pp[k];i!=-1;i=e[i].next)
        {
            if(!vis[e[i].to]&&e[i].w<closedge[e[i].to])
            {
                closedge[e[i].to]=e[i].w;
                t1.d=e[i].w;
                t1.u=e[i].to;
                que.push(t1);
            }
        }
    }
}
    Prim算法一般用于稠密图的情况,Kruscal算法则一般用于稀疏图的情况。在下面的Kruscal算法中还用到了并查集。

#define N 1000
struct Edge
{
    int u,v,w;
}e[100000];
int parent[N],cnt,n;
int Find(int x)
{
    if(parent[x]<0)
        return x;
    int r=Find(parent[x]);
    parent[x]=r;
    return r;
}
void Union(int x,int y)
{
    int a=Find(x),b=Find(y);
    if(a!=b)parent[a]=b;
}
int cmp(const void* a,const void* b)
{
    return ((struct Edge*)a)->w-((struct Edge*)b)->w;
}
void kruscal()
{
    int i,j,k=0;
    memset(parent,-1,sizeof(parent));
    qsort(e,cnt,sizeof(struct Edge),cmp);
    for(i=0;i<cnt;i++)
        if(Find(e[i].u)!=Find(e[i].v))
        {
            Union(e[i].u,e[i].v);
            k++;
            if(k==n-1)
                break;
        }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值