图论之最小生成树

  • prim算法

    基本思想:先从无向图中标记若干顶点,再从标记顶点中选择权值最小的边,且这条边的另一顶点未被标记,直到所有的点都已被标记。

    算法实现:用数组vis表示点的标记情况,数组low表示与点关联的最小权值情况。  

 1 int prim(int n)
 2 {
 3     int i,j;
 4     int min,pos;
 5     int ans=0;
 6 
 7     vis[0]=1; pos=0;
 8 
 9     for(i=0; i<n; i++)
10         if(i!=pos) low[i]=dis[pos][i];
11 
12     for(i=0; i<n; i++)//n-1次循环
13     {
14         min = MaxInt;
15         for(j=0; j<n; j++)
16             if(vis[j]==0 && min>low[j])
17             {
18                 min=low[j];
19                 pos=j;
20             }
21 
22             ans+=min;
23             vis[pos]=1;
24 
25         for(j=0; j<n; j++)
26             if(vis[j]==0 && low[j]>dis[pos][j])//更新最小权值
27                 low[j]=dis[pos][j];
28     }
29     return ans;
30 }
  • kruskal算法 

    基本思想:对于无向图中所有的边,每次从当前为选择的边中选择权值最小且不会与已被选择的边构成环的边,直到所有的点都被标记,其中判断所选边是否构成环可以采用并查集来实现。

    算法实现:用数组pre来记录并查集中点的根节点的情况

typedef struct edge
{
    int a;
    int b;
    int value;
};
edge map[MAX];
int pre[MAX];

void init()//并查集初始化
{
    for(int i=0; i<=MAX; i++)
        pre[i]=i;
}

int find(int x)//查找x的根节点并对路径进行压缩
{
    int r=x;
    while(pre[r]!=r)//r=pre[r]表示r为根节点
        r=pre[r];

    //路径压缩
    int j,i=x;
    while(i!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }

    return r;
}

bool join(int x,int y)//判断是否成环
{
    int root1=find(x);
    int root2=find(y);

    if(root1==root2) return false;

    pre[root1]=root2;//合并
    return true;
}

int kruskal()
{
    int i=0,a,b;
    int ans=0;
    int num=1;

    while(num<n)
    {
        a=map[i].a;
        b=map[i].b;
        if(join(a,b))
        {
            ans+=map[i].value;
            num++;
        }
        i++;
    }
    return ans;
}

  

posted @ 2015-03-05 23:06  流浪集  阅读(110)  评论(0编辑  收藏  举报