导航

prim算法查找最小生成树

Posted on 2015-09-26 16:27  骄阳照林  阅读(282)  评论(0编辑  收藏  举报

我们在图的定义中说过,带有权值的图就是网结构。一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边。所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接起来,并且使得权值的和最小。综合以上两个概念,我们可以得出:构造连通网的最小代价生成树,即最小生成树(Minimum Cost Spanning Tree)。找连通图的最小生成树,经典的有两种算法,普里姆算法和克鲁斯卡尔算法。

prim实现:

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Prim {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			int n = sc.nextInt();
			int m = sc.nextInt();
			if (n == 0 && m == 0) {
				break;
			}
			int[][] map = new int[n][n];
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					map[i][j] = Integer.MAX_VALUE;
				}
			}

			for (int i = 0; i < m; i++) {
				int u = sc.nextInt();
				int v = sc.nextInt();
				int w = sc.nextInt();
				map[u][v] = w;
				map[v][u] = w;
			}
			Edge[] e = new Edge[n];
			prim(map, e, n);
			for (int i = 0; i < n - 1; i++) {
				System.out.println(e[i].from + " " + e[i].end + " "
						+ e[i].weight);
			}

		}

	}

	static void prim(int[][] map, Edge[] e, int n) {
		Set<Integer> set1 = new HashSet<>();
		Set<Integer> set2 = new HashSet<>();
		set1.add(0);
		for (int i = 1; i < n; i++)
			set2.add(i);
		int min = Integer.MAX_VALUE;
		int k=0;
		while (!set2.isEmpty()) {
			min = Integer.MAX_VALUE;
			int flag1 = 0;
			int flag2 = 0;
			for (int i : set1) {
				for (int j : set2) {
					if (map[i][j] < min) {
						min = map[i][j];
						flag1 = i;
						flag2 = j;
					}
				}
			}
			set1.add(flag2);
			set2.remove(flag2);
			e[k]=new Edge();
			e[k].from=flag1;
			e[k].end=flag2;
			e[k].weight=min;
			k++;
		}
		 
	}

	private static class Edge {
		int from;
		int end;
		int weight;
	}

}