今天来复习一下prime算法,发现好多东西,后来看的和以前看的会有一些不一样,在理解和思考上也会不一样,所以、还是多看看,多想想、、、
prime适合求稠密网的最小生成树,时间复杂度为O(n*n)。
过程:
1. 选择一个起点(一般是第一个点v0),将这个结点加入集合中,然后,对非集合中的顶点遍历,找出与 v0 关联的边权值最小的那个点,将此顶点加入集合中。并已该点作为起点。
2. 递归重复步骤1,直到已连接所有点(或者符合题目要求的点),结束此过程。
3. 集合中的点,就为该生成树中的点,按顺序连接起来,得到的就是这个图的最小生成树。
下面我还是来几张图,将就着理解一下、
下面是模版:
这是比较早之前写的了,也是最基础呃,现在感觉可以有优化的方法,复杂度可以不用达到n*n、、
int prim()
{
int i, j, k;
int ans = 0;
int min, t;
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i ++)
{
dis[i] = map[1][i]; // 各点到第一个点的距离、
}
vis[1] = 1; // 一般都是第一个点做起点,标记加入集合
for(i = 1; i < n; i ++)
{
min = Max;
for(j = 1; j <= n; j ++)
{
if(!vis[j] && dis[j] < min) // 取出最小的值
{
min = dis[j];
t = j;
}
}
if(min == Max) // 如果没有找到,退出(这里我理解的不是很清楚)
break;
ans += min;
vis[t] = 1;
for(k = 1; k <= n; k ++) // 更新dis
{
if(!vis[k] && dis[k] > map [t][k])
dis[k] = map[t][k];
}
}
return ans;
}
例题:
HDU 1233 还是畅通工程 链接: http://acm.hdu.edu.cn/showproblem.php?pid=1233
#include<stdio.h>
#include<string.h>
#define Max 1000000
int ans;
int map[110][110];
int dis[110];
int vis[110];
int n;
int prim()
{
int i, j, k;
int ans = 0;
int min, t;
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i ++)
{
dis[i] = map[1][i];
}
vis[1] = 1;
for(i = 1; i < n; i ++)
{
min = Max;
for(j = 1; j <= n; j ++)
{
if(!vis[j] && dis[j] < min)
{
min = dis[j];
t = j;
}
}
if(min == Max)
break;
ans += min;
vis[t] = 1;
for(k = 1; k <= n; k ++)
{
if(!vis[k] && dis[k] > map [t][k])
dis[k] = map[t][k];
}
}
return ans;
}
int main()
{
int i;
int m;
int a, b, c;
while(~scanf("%d",&n)&&n)
{
int m = n*(n - 1)/2;
for(i = 0; i < m; i ++)
{
scanf("%d%d%d", &a, &b, &c);
map[a][b] = c;
map[b][a] = c;
}
printf("%d\n",prim());
}
return 0;
}