最小生成树

 
普里姆算法:
有n个顶点,每两个顶点之间都有权值;
从顶点v0 开始构造最小生成树T。
low数组记录已经构成树的顶点和未构成树的顶点之间的边的权值。
循环n-1次
{
   找到low数组里面最小的权值的边,并加入构成树的顶点数组中。
   更新low数组内边的权值。
}
 
代码:
 
#include <stdio.h>
#include <iostream>
#include <cstring>
using namespace std;
#define MaxInt 0xfffffff
#define N 105
int map[N][N],low[N]; //map记录节点间的权值  low记录当前选中点与未选中点的权值
bool v[N];   //标记数组
int n;
int prim()
{
    int i, j, pos, min, sum=0; //记录最小生成树权值之和
    pos=1;             //记录新加入的点的下标

    v[1] = 1;
    for(i=1; i<=n; i++) //更新low数组
        if(i!=pos)
            low[i] = map[pos][i];
    for(i=1; i<n; i++)
    {
        min = MaxInt;
        for(j=1; j<=n; j++)
            if(!v[j] && low[j]<min)//找到最小的边,记录其顶点
            {
                min = low[j];
                pos = j;
            }
        sum += min;
        v[pos]= 1;
        for(j=1; j<=n; j++)
            if(!v[j] && low[j]>map[pos][j]) //更新low数组内的权值
                low[j] = map[pos][j];
    }
    return sum;
}
int main()
{
    int i, j;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
            scanf("%d", &map[i][j]);
        memset(v, 0, sizeof(v));
        printf("%d\n",prim());
    }
    return 0;
}
克鲁卡斯算法:
自我理解:  
就是运用并查集。
先将所有的边排序,从最小的开始查找。
每条边都有两个顶点,如果两个顶点不是在同一个集合,则进行并查集合并。
所有的边合并成同一个集合时,最小生成树也就构成(因为每次都是合并的都是当前最短的边)。
 
代码:
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define MaxInt 0xfffffff
#define N 105
struct node
{
    int i, j;
    int low;
} map[5000];
int v[N];   //并查集数组
int n, k;   //n顶点数 k边数
bool cmp(const node &a, const node &b) //排序(小—>大)
{
    return a.low<b.low;
}
int find(int t) //并查集的找根
{
    while(v[t]!=t)
        t=v[t];
    return t;
}
int S()
{
    int sum=0, i;
    sort(map, map+k, cmp); //对每条边按照权值大小排序(小的在前)
    for(i=1; i<=n; i++)    //并查集初始化
        v[i]=i;
    for(i=0; i<k; i++)     //从权值最小的边开始
    {
        int v1=map[i].i;   //边的顶点
        int v2=map[i].j;
        int s1=find(v1);   //看两个顶点是否已经属于一个集合
        int s2=find(v2);
        if(s1!=s2)
        {
            sum += map[i].low;
            v[s1]=s2;
        }
    }
    return sum;
}
int main()
{
    int i, j, a;
    while(scanf("%d",&n)!=EOF)
    {
        for(k=0, i=1; i<=n; i++)
            for(j=1; j<=n; j++)
            {
                scanf("%d", &a);
                if(i<j)
                {
                    map[k].i=i;
                    map[k].j=j;
                    map[k++].low=a;
                }
            }
        memset(v, 0, sizeof(v));
        printf("%d\n", S());
    }
    return 0;
}

 

posted @ 2015-09-22 17:00  马晨  阅读(128)  评论(0)    收藏  举报