prim算法思想
㈠ 话说最小生成树的prim算法和kursual算法的区别
prim算法和kurskal算法解决的问题是相同的,都用来求最小生成树。从某一结点A出发,按照一定次序,经过中间结点集Q中的每一个结点,得到最短路径,称为最小生成树。
kurskal算法的核心思想就是“尽可能的选取短边”,按照长度从小到大依次加入生成树;prim算法引入一个概念——生长点(和非生长点),每次加入的最短边是与生长点相邻的最短边,初始状态下,唯一的一个点就是生长点,随着新边的加入,每次加入的边的末端就是生长点,若某一生长点已经没有相邻边可以加入,就回溯到上一级结点,加入新边,直到Q中的所有结点都加入图中。
一般教材编的都很清楚的,结合我这个,再看看书,相信你很快就会明白的。
㈡ 什么是Prim算法
Prim算法
Prim算法用于求无向图的最小生成树
设图G =(V,E),其生成树的顶点集合为U。
①、把v0放入U。
②、在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。
③、把②找到的边的v加入U集合。如果U集合已有n个元素,则结束,否则继续执行②。
其算法的时间复杂度为O(n^2)
Prim算法实现:
(1)集合:设置一个数组set[i](i=0,1,..,n-1),初始值为 0,代表对应顶点不在集合中(注意:顶点号与下标号差1)
(2)图用邻接阵表示,路径不通用无穷大表示,在计算机中可用一个大整数代替。
参考程序
/* Prim.c
Copyright (c) 2002, 2006 by ctu_85
All Rights Reserved.
*/
/* The impact of the situation of articulation point exists can be omitted in Prim algorithm but not in Kruskal algorithm */
#include "stdio.h"
#define maxver 10
#define maxright 100
int main()
{
int G[maxver][maxver],in[maxver]=,path[maxver][2];
int i,j,k,min=maxright;
int v1,v2,num,temp,status=0,start=0;
restart:
printf("Please enter the number of vertex(s) in the graph:\n");
scanf("%d",&num);
if(num>maxver||num<0)
{
printf("Error!Please reinput!\n");
goto restart;
}
for(j=0;j<num;j++)
for(k=0;k<num;k++)
{
if(j==k)
G[j][k]=maxright;
else
if(j<k)
{
re:
printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);
scanf("%d",&temp);
if(temp>=maxright||temp<-1)
{
printf("Invalid input!\n");
goto re;
}
if(temp==-1)
temp=maxright;
G[j][k]=G[k][j]=temp;
}
}
for(j=0;j<num;j++)
{
status=0;
for(k=0;k<num;k++)
if(G[j][k]<maxright)
{
status=1;
break;
}
if(status==0)
break;
}
do
{
printf("Please enter the vertex where Prim algorithm starts:");
scanf("%d",&start);
}while(start<0||start>num);
in[start-1]=1;
for(i=0;i<num-1&&status;i++)
{
for(j=0;j<num;j++)
for(k=0;k<num;k++)
if(G[j][k]<min&&in[j]&&(!in[k]))
{
v1=j;
v2=k;
min=G[j][k];
}
if(!in[v2])
{
path[i][0]=v1;
path[i][1]=v2;
in[v1]=1;
in[v2]=1;
min=maxright;
}
}
if(!status)
printf("We cannot deal with it because the graph is not connected!\n");
else
{
for(i=0;i<num-1;i++)
printf("Path %d:vertex %d to vertex %d\n",i+1,path[i][0]+1,path[i][1]+1);
}
return 1;
}
Prim算法。
设图G =(V,E),其生成树的顶点集合为U。
①、把v0放入U。
②、在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。
③、把②找到的边的v加入U集合。如果U集合已有n个元素,则结束,否则继续执行②。
其算法的时间复杂度为O(n^2)
参考程序
//Prim 算法 读入顶点数(n)、边数(m),边的起始点和权值 用邻接矩阵储存
//例如
//7 12 (7个顶点12条边)
//1 2 2
//1 4 1
//1 3 4
//2 4 3
//2 5 10
//3 4 2
//4 5 7
//3 6 5
//4 6 8
//4 7 4
//5 7 6
//6 7 1
#include <stdio.h>
#include <string.h>
int main()
{
int m , n;
int a[201][201] , mark[201] , pre[201] , dist[201];
int s , t , w;
int i , j , k , min , tot;
freopen("Prim.txt" , "r" , stdin);
//读入数据
memset(a , 0 , sizeof(a));
scanf("%d %d" , &n , &m);
for (i = 0; i < m; i ++)
{
scanf("%d %d %d" , &s , &t , &w);
a[s][t] = w; a[t][s] = w;
}
//赋初值
memset(mark , 0 , sizeof(mark));
memset(pre , 0 , sizeof(pre));
memset(dist , 9999 , sizeof(dist));
dist[1] = 0;
//Prim
for (i = 1; i <= n; i ++)
{
min = 9999; k = 0;
for (j = 1; j <= n; j ++)
if ((mark[j] == 0) && (dist[j] < min)) {min = dist[j]; k = j;}
if (k == 0) break;
mark[k] = 1;
for (j = 1; j <= n; j ++)
if ((mark[j] == 0) && (a[k][j] < dist[j]) && (a[k][j] > 0))
{
dist[j] = a[k][j];
pre[j] = k;
}
}
tot = 0;
for (i = 1; i <= n; i ++) tot += dist[i];
printf("%d\n" , tot);
return 0;
}
㈢ 最小生成树
所谓最小生成树,就是在一个具有N个顶点的带权连通图G中,如果存在某个子图G',其包含了图G中的所有顶点和一部分边,且不形成回路,并且子图G'的各边权值之和最小,则称G'为图G的最小生成树。 由定义我们可得知最小生成树的三个性质:
•最小生成树不能有回路。
•最小生成树可能是一个,也可能是多个。
•最小生成树边的个数等于顶点的个数减一。宴昌 本文将介绍两种最小生成树的算法,分别为克鲁斯卡尔算法(Kruskal Algorithm)和普利姆算法(Prim Algorithm)。
克鲁斯卡尔算法的核心思想是:在带权连通图中,不断地在边集合中找到最小的边,如果该边满足得到最小生成树的条件,就将其构造,直到最后得到一颗最小生成树。
克鲁斯卡尔算法的执行步骤:
第一步:在带权连通图中,将边的权值排序;
第二步:判断是否需要选择这条边(此时图中的边已按权值从小到大排好序)。判断的依据是边的两个顶点是乱芦否已连通,如果连通则继续下一条;如果不连通,那么就选择晌陪扒使其连通。
第三步:循环第二步,直到图中所有的顶点都在同一个连通分量中,即得到最小生成树。
下面我用图示法来演示克鲁斯卡尔算法的工作流程,如下图:
㈣ 普里姆算法是什么
普里姆(Prim)算法,和克鲁斯卡尔算法一样,是用来求加权连通图的最小生成树的算法。
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。
该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。
基本思想:
对于图G而言,V是所有顶点的集合;现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T存放G的最小生成树中的边。
从所有uЄU,vЄ(V-U) (V-U表示出去U的所有顶点)的边中选取权值最小的边(u, v),将顶点v加入集合U中,将边(u, v)加入集合T中,如此不断重复,直到U=V为止,最小生成树构造完毕,这时集合T中包含了最小生成树中的所有边。
㈤ 鐢诲嚭绠楁硶镄勬祦绋嫔浘
瀵逛簬杩欑嶆瘆杈冮珮绾х殑绠楁硶浠g爜鐩存帴鐪嬬▼搴忎细姣旇缉钂欙纴浣犲氨鍏夌湅鎴戠殑绠楁硶娴佺▼钖э纴prim绠楁硶鐢ㄧ殑鏄璐蹇幂畻娉旷殑镐濇兂锛屽嵆姣忎竴姝ラ兘浣滃嚭灞閮ㄧ殑链浼樿В锛屽叧浜巅rim 绠楁硶涓轰粈涔堣兘鐢ㄨ椽蹇幂畻娉旷殑璇佹槑锛屼綘鍙浠ュ弬钥冦婅$畻链虹畻娉曡捐′笌鍒嗘瀽銆嬭繖链涔︺傦纸鎴戝弽姝d笉𨱍崇湅闾d箞镞犺亰镄勮瘉鏄庯纴涔熺湅涓嶆槑锏斤纴锻靛懙锛夈
瀹氢箟涓涓闆嗗悎v 鍜 a锛屽叾涓璿鏄鍏ㄤ綋鑺傜偣锛堟昏妭镣规暟涓簄锛夌殑闆嗗悎锛寁鍒濆嬩负绌恒傚畾涔変竴涓璁板綍链灏忕敓鎴愭暟杈规暟镄勫彉閲廲銆
1.鍦╲涓浠婚変竴涓鑺傜偣锛屽苟锷犲叆鍒瘾涓銆傚湪v涓鍒犻櫎璇ヨ妭镣广
2.阃変竴涓鍦ㄦ墍链夎繛鎺v闆嗗悎鍜宎闆嗗悎𨱒冨兼渶灏忕殑杈癸纸鍗充竴涓鑺傜偣鏄痸镄勬煇涓涓鑺傜偣锛屼竴涓鏄痑涓镄勬煇涓涓鑺傜偣锛
3銆傚皢涓や釜鑺傜偣杩炴帴銆傚皢c锷1
4.灏嗙3姝ユ墠鍦╲涓鑺傜偣鍒犻櫎骞跺姞鍏ュ埌a涓.
5.濡傛灉c涓簄-1鍒椤畬鎴愭渶灏忕敓鎴愭爲锛屽惁鍒椤洖鍒扮2姝ャ
鏄庣槠浜嗘病锛熶笉鏄庣槠鍐嶉梾鎴戝晩锛屽笇链涘逛綘链夋墍甯锷┿