最小生成树之Prim的应用

现在是凌晨时分 本来很早就想写了 被一道搜索题卡到现在 至今没有A出 等A出以后 一定要写出来 ....

Prim:它是 基于 图的顶点 的算法

其实 这个算法 是很容易理解的

首先 你任意选取一个点 加入MST集合中 这里的MST即最小生成树集合

然后你对所有不属于MST的点 进行循环遍历寻找权值最小的边

并且 再每加入一个点后 就刷新其余点到这个MST集合的相对最短距离(这是核心步骤)

个人 感觉Prim算法 还是很基础的 当你不考虑heap优化的情况下

我们还是 那道题说说吧

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=38

 1 #include <stdio.h>
 2 #include <string.h>
 3 #define MAX 100000000
 4 int map[505][505];//邻接矩阵
 5 int dis[505];//距离 并且指这条边是以dis[i]的i为结尾的
 6 int visited[505];
 7 int n,m;
 8 
 9 int prim()
10 {
11     int i,j,k,ans=0,min,t;
12     memset(visited,0,sizeof(visited));//起初标记所有点都未被访问
13     for(i=1;i<=n;i++)
14         dis[i]=map[1][i];//所有最小权值边起初都是以相同的起始点1开始
15     visited[1]=1;//从1开始访问
16     for(i=1;i<n;i++)//因为是最小生成树 所以当有n个顶点的时候 只有n-1条边
17     {
18         min=MAX;//将Min设置的 无穷大 以便来标记
19         for(j=2;j<=n;j++)
20         {
21             if( !visited[j] && dis[j]<min )//j的要求未被访问 并且可以得到相对最小距离
22             {
23                 min=dis[j];
24                 t=j;
25             }
26         }
27         if(min==Max)//如果这个if成立相当于 上面没有一个j进入MST中 所有可以直接break
28               break;
29         ans+=min;
30         visited[t]=1;
31 
32         for(k=2;k<=n;k++)
33         {
34             if( !visited[k] && dis[k]> map[t][k] )//这边 我用大于号 才能刷新最下值
35                 dis[k]=map[t][k];
36         }
37 
38     }
39     return ans;
40 }
41 
42 int main()
43 {
44     int t,a,b,c,i,j,min;
45     scanf("%d",&t);
46     while (t--)
47     {
48         scanf("%d %d",&n,&m);
49         for(i=1;i<=n;i++)
50         {
51             for(j=1;j<=n;j++)
52                 map[i][j]=MAX;
53         }
54         for(i=1;i<=m;i++)
55         {
56             scanf("%d%d%d",&a,&b,&c);
57             map[a][b]=map[b][a]=c;
58         }
59         min=MAX;
60         for(i=1;i<=n;i++)
61         {
62             scanf("%d",&a);
63             if(a<min)
64                 min=a;
65         }
66         printf("%d\n",min+prim());
67     }
68 }
View Code

这边 我给出的是邻接矩阵的实现方式  你可以自己去实现 邻接表的方式   而我会在下次 讲到欧拉图的时候 使用邻接表

其实 这段以前写过的代码 还有很多可以优化的细节 例如:vis数组 用bool实现   MAX的设置使用16进制来实现

我还想提的一点是: Prim算法的思想 与 最短路中Dijkstra的思想 实在是太像了

最大的区别就是:Dijk数组含义上的不同:这里是指顶点到MST集合的最短距离 Dijkstra算法中是指顶点到起始点的最短距离

我想 对于每个算法 了解它的思想 才是最重要的

 

posted @ 2014-04-14 00:28  radical  阅读(586)  评论(0编辑  收藏  举报