prim算法
试用场景:稠密图
存储结构:邻接矩阵
算法思路:维护一个集合,找到每次离集合最近的点,然后把该点加入到该集合,并使用这个点去更新其他点到集合的距离。(类似于dijkstra算法,dijkstra算法维护的是到源点的距离)
实现代码:
int prim(){
int[] dist = new int[N];
boolean[] st = new boolean[N];
Arrays.fill(dist , inf);
int res = 0;
for(int i = 0 ; i < n ;i ++){
int t = -1;
for(int j = 1 ; j <= n ; j ++)
if(!st[j] && (t== -1 || dist[j] < dist[t]) )
t = j;
if( i!= 0 && dist[t] == inf ) return inf;
if( i!= 0 ) res += dist[t];
for(int j = 1 ;j <= n ;j ++)
dist[j] = Math.min( dist[j] , g[t][j] );
st[t] = true;
}
return res;
}
kruskal算法
适用场景:稀疏图
存储结构:Edge(a ,b ,w)数组
算法思路:维护一个集合,每次选取最小的边,判断是否可以加入集合(a,b两个结点属于两个不同的集合,然后两个集合合并)
采用并查集来判断 a ,b是否属于两个不同的集合,维护集合的关系
实现代码:
static Edge[] edges = new Edge[M];
static int[] p = new int[N];
static class Edge{
int a , b , w;
Edge(int x , int y ,int z){a = x ; b = y ; w = z;}
}
static{
for(int i = 1 ; i < N ;i ++) p[i] = i;
}
static int find(int x){
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
static int kruskal(){
Arrays.sort( edges , 0 , m , (x,y)->x.w - y.w );
int res = 0 , cnt = 0;
for(int i = 0 ; i < m ;i ++ ){
int a = edges[i].a ,b = edges[i].b , w = edges[i].w;
a = find(a);
b = find(b);
if(a != b){
res += w;
cnt++;
p[a] = b;
}
}
return cnt == n-1 ? res : -1;
//生成树中有n-1条边,cnt小于n-1则说明至少有两个集合是不连通的。
}