关于Prime算法的从入门到升天的讲解

说到最小(大)生成树的典型算法当然是Prime和Kruskal了。
Kruskal比较好理解就不说了。这里主要是谈一谈Prime算法。

Prime算法的核心步骤:
在带权连通图中假设V是包含所有顶点的集合, U是已经在最小生成树中的节点的集合,从图中任意某一顶点v开始,此时集合U={v}。
重复执行下述操作:
在所有u∈U,w∈V-U的边(u,w)∈E中找到一条权值最小的边,将(u,w)这条边加入到已找到边的集合,并且将点w加入到集合U中,当U=V时,就找到了这颗最小生成树。

这样讲可能对新人来说比较难理解。我们可以这样想:
首先最小生成树他是一颗“树”。树的一大核心思想就是可以把问题下移到子树上从而达到简化,细化问题的目的。那么一颗树最小的问题就变成了他的最小子树加一条权值最小的边的问题。
那么那条最小的边是哪条呢?我们可以这样想,我们最后的目的是把所有点连成一颗树同时使树的权值和最小,那么我们根本不关心新的点会连到树的哪个点上,只要边权值小就行。那么我们可以把已有的树(集合U)看成一个“点”,只需要不断更新这个“点”到其他边的权值,然后每次从其中选一个最小的连上就行。

来看道例题:

Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course.
Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms.
Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm.
The distance between any two farms will not exceed 100,000.

题意懒的看的无所谓,大致就是告诉你有多少个点,然后给你这些点间的距离,让你用最短的距离把所有点连起来。

Input

The input includes several cases. For each case, the first line contains the number of farms, N (3 <= N <= 100). The following lines contain the N x N conectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem. 

Output

For each case, output a single integer length that is the sum of the minimum length of fiber required to connect the entire set of farms. 

Sample Input

4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0

Sample Output

28

这里我们只用这道题的背景,不讲这道题(也不是啥难题,就是prime入门题)。
如果想看这道题的详细代码请点击这里:http://blog.csdn.net/vocaloid01/article/details/78723779

关键是看Prime实现部分:

#define INF 0x3f3f3f3f

int N;
int map[105][105];

bool book[105];//true为已经加入树的,false则相反 
int lenth[105];//注意有的博客这里解释为根到各个点的距离,其实应该是“树”到各个点的距离 
int Prime()
{
    memset(book,false,sizeof(book));
    int sum = 0;
    book[0] = true;//这里选0点为根 
    for(int i=1 ; i<N ; i++)
    {
        lenth[i] = map[0][i];//刚开始集合就是0点 
    }

    for(int i=1 ; i<N ; i++)
    {
        int min = INF;
        int node;
        for(int j=1 ; j<N ; j++)//选出与“树”相连且权值最小的边 
        {
            if(book[j] == false && lenth[j]<min)
            {
                min = lenth[j];
                node = j;
            }
        }
        sum += min;
        book[node] = true;//把新的点加入树中 
        for(int i=1 ; i<N ; i++)//根据新加入的点更新“树”到其他点的距离。 
        {
            if(book[i] == false && lenth[i]>map[node][i])
            {
                lenth[i] = map[node][i];
            }
        }
    }
    return sum;//返回结果 
}

由于PS用的比较差(就是懒(:з」∠))就没画图了,希望能帮到初学者吧。
另外有啥不对的地方也欢迎指正。至于推荐题吧。。。。就上面那一道就不错,
嗯嗯嗯~(NO B 数 in my heart)

posted @ 2017-12-05 19:56  Assassin_poi君  阅读(1064)  评论(0编辑  收藏  举报