Prim算法——求无向图的最小生成树

基准时间限制:1 秒 空间限制:131072 KB 分值: 0  难度:基础题
 收藏
 关注
N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。
Input
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000)
第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
Output
输出最小生成树的所有边的权值之和。
Input示例
9 14
1 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8
Output示例
37

具体过程就不多说,这是一个按点集求最小生成树的算法。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h> 
#define MaxInt 0x3f3f3f3f
typedef long long ll;
int map[1001][1001];    //邻接矩阵
int low[1001];          //记录2个点间最小权值 
int vis[1001];          //标记某点是否已访问
int n,m;                  //点的数量 
ll prim(){
	int i,j,pos,min;
	ll result=0;
	memset(vis,0,sizeof(vis)); //标记所有点没有被访问
	vis[1]=1;pos=1;      //从某点开始,分别标记和记录该点
	for(i=1;i<=n;i++)
		if(i!=pos)
			low[i]=map[pos][i]; //第一次给low数组赋值
	//运行n-1次,找出最小权值并记录位置	
	for(i=1;i<n;i++){
		min=MaxInt;
		for(j=1;j<=n;j++)
			if(vis[j]==0&&min>low[j]){
				min=low[j];
				pos=j;
			} 
		if(MaxInt==min)
			return -1;        //不连通 
		result=result+min;    //最小权相加
		vis[pos]=1;           //标记该点
		//更新权值
		for(j=1;j<=n;j++)
			if(vis[j]==0&&low[j]>map[pos][j])
				low[j]=map[pos][j]; 
	} 
	return result;
}
int main(){
	int i,j;
	while(scanf("%d %d",&n,&m)!=EOF){
		int x,y,w;
		memset(map,MaxInt,sizeof(map)); //首先记录所有边的权为最大值
		for(i=1;i<=m;i++){
			scanf("%d %d %d",&x,&y,&w);
			map[x][y]=map[y][x]=w;
		}	
		ll s=prim();
		printf("%lld\n",s); 
	}
	return 0;
}
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		while (input.hasNext()) {
			int n = input.nextInt();
			int m = input.nextInt();

			int[][] map = new int[n + 1][n + 1];
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= n; j++) {
					map[i][j] = Integer.MAX_VALUE;
				}
			}
			for (int i = 0; i < m; i++) {
				int s = input.nextInt();
				int e = input.nextInt();
				int v = input.nextInt();
				map[s][e] = v;
				map[e][s] = v;
			}
			long res = prim(map);
			System.out.println(res);
		}
		input.close();
	}

	public static long prim(int[][] map) {
		long res = 0;
		int len = map.length;
		int[] vis = new int[len];
		int[] low = new int[len];
		int currNode = 1;
		vis[1] = 1;
		
		int[] path = new int[len]; // 存入path[i] 点到 i点此时距离最短
		for (int i = 1; i < len; i++) {
			low[i] = map[currNode][i];
			
			path[i] = 1;
		}

		for (int i = 1; i < len - 1; i++) {
			int min = Integer.MAX_VALUE;
			for (int j = 1; j < len; j++) {
				if (vis[j] == 0 && min > low[j]) {
					min = low[j];
					currNode = j;
				}
			}
			if (min == Integer.MAX_VALUE)
				return -1; // 不连通

			res += min;
			vis[currNode] = 1;
			//System.out.println(path[currNode] + "---->" + currNode + " == " + min);

			for (int j = 1; j < len; j++) {
				if (vis[j] == 0 && low[j] > map[currNode][j]) {
					low[j] = map[currNode][j];
					
					path[j]=currNode;
				}
			}
		}
		return res;
	}

	public static void print(int[] res) {
		for (int i = 1; i < res.length; i++) {
			System.out.print(res[i] + " ");
		}
		System.out.println();
	}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);  
        while (input.hasNext()) {  
            int n = input.nextInt();  
            int m = input.nextInt();  
            List<Node> list = new ArrayList<>();
            for (int i = 0; i < m; i++) {  
                int s = input.nextInt();  
                int e = input.nextInt();  
                int v = input.nextInt();  
                Node node = new Node(s-1, e-1, v);
                list.add(node);
            }
            Collections.sort(list, new Comparator<Node>() {
            	@Override
            	public int compare(Node o1, Node o2) {
            		return o1.v - o2.v;
            	}
			});
            //print(list);
            
			int[] pre = new int[n];
			for (int i = 0; i < n; i++) {
				pre[i] = i;
			}
    		
            long res = kruskal(list,pre);  
            System.out.println(res);  
        }  
        input.close();  
	}

	private static long kruskal(List<Node> list,int[] pre) {
		
		long res = 0;
		for(int i = 0;i<list.size();i++){
			int fx = find(pre, list.get(i).s);
			int fy = find(pre, list.get(i).e);
			if(fx != fy){
				res += list.get(i).v;
				pre[fx] = fy;
				//System.out.println((list.get(i).s + 1) +"---->" +(list.get(i).e + 1) + " == " + list.get(i).v);
			}
		}
		
		return res;
	}
	
	public static int find(int[] pre, int x) {
		int r = x;
		while (pre[r] != r) {
			r = pre[r];
		}
		// 路径压缩
		int i = x;
		int j;
		while (i != r) {
			j = pre[i];
			pre[i] = r;
			i = j;
		}

		return r;
	}
	
	public static void join(int[] pre, int x, int y){
		int fx = find(pre, x);
		int fy = find(pre, y);
		if(fx != fy){
			pre[fx] = fy;
		}
	}
	
	public static void print(List<Node> list){
		for (Node node : list) {
			System.out.println(node.s + " -- > " +node.e + " == " + node.v);
		}
	}
}
class Node{
	public int s;
	public int e;
	public int v;
	public Node(int s, int e, int v) {
		super();
		this.s = s;
		this.e = e;
		this.v = v;
	}
}





 
  

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值