POJ1287 (最小生成树) 中文版

问题描述:

  您被分配在广域内的某些点之间设计网络连接。在该区域中为您提供了一组点,以及可能连接成对点的电缆的一组可能路线。对于两点之间的每条可能路线,将为您提供在该路线上连接各点所需的电缆长度。请注意,两个给定点之间可能存在许多可能的路线。假定给定的可能路线(直接或间接)连接区域中的每两个点。
  您的任务是设计该区域的网络,以使每两个点之间都具有连接(直接或间接)(即,所有点都是互连的,但不一定是通过直接电缆),并且总长度为使用的电缆极少。

输入量:

  输入文件由许多数据集组成。每个数据集定义一个所需的网络。集合的第一行包含两个整数:第一行定义给定点的数量P,第二行定义点之间的给定路线的数量R。以下R线定义了点之间的给定路线,每条给出三个整数:前两个数字标识点,第三个给出路线的长度。数字用空格分隔。仅给出一个数字P = 0的数据集表示输入的结尾。数据集用空行分隔。
  最大点数为50。给定路线的最大长度为100。可能的路线数是无限的。用1到P(含)之间的整数标识节点。两个点i和j之间的路线可以指定为ij或j i。

输出量:

  对于每个数据集,在单独的一行上打印一个数字,以给出用于整个设计网络的电缆的总长度。

样本输入

1 0

2 3
1 2 37
2 1 17
1 2 68

3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32

5 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 12

0

样本输出

0
17
16
26

解题思路:

  这是典型的最小生成树题型,直接套模板。
  模板参考:最小生成树



代码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class POJ1287 {
	static int p;   //点的数量
	static int r;	//边的数量
	static int[] parent;   //并查集的数组,存储节点所在树的根
	static ArrayList<Integer> res = new ArrayList<Integer>(); //统计确定边权值的和
	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		while(true){
			p = scanner.nextInt();
			if(p==0) break;    //点的数量为0,结束循环
			r = scanner.nextInt();
			if(r == 0){  //如果边的数量等于0,不需要计算,直接输出0
				res.add(0);
				continue;
			}
			//从1开始计算,因为输入的数据点的编号是从1开始的
			parent = new int[p+1];   //并查集的数组,存储节点所在树的根 
			Arrays.fill(parent, -1);  //初始化
			ArrayList<Edge> sum = new ArrayList<Edge>();  //存储结果
			Edge[] arr = new Edge[r];
			for(int i=0; i<r; i++){  //创建对象,否则下面会出现空指针异常
				arr[i] = new Edge();
			}
			for(int i=0; i<r; i++){   //接收边的数据
				arr[i].start = scanner.nextInt();
				arr[i].end = scanner.nextInt();
				arr[i].distance	= scanner.nextInt();
			}
			Arrays.sort(arr);  //升序排序
			int count = 0;   //y以确定边的数量
			for(int i=0; count<p-1; i++){
				Edge e = arr[i];
				if( union(e.start,e.end) ){
					sum.add(e);   //添加边
					count++;
				}
			}
			int temp = 0;
			for(Edge e:sum){
				temp = temp + e.distance;
			}
			res.add(temp);   //将结果添加进来
		}
		
		//打印结果
		for(Integer num:res){
			System.out.println(num);
		}
	}

	//将两个节点所在的集合进行合并,如果合并失败返回false
	private static boolean union(int x, int y) {
		int xroot = findRoot(x);
		int yroot = findRoot(y);
		if(xroot == yroot){ //同一个集合,会产生环
			return false;
		}
		parent[xroot] = yroot;    //将x的根节点指向y的根节点
		return true;
	}

	//查找节点所在树的根节点
	private static int findRoot(int x) {
		int t = x;
		while(parent[t]!= -1){
			t = parent[t];
		}
		return t;
	}
}

class Edge implements Comparable<Edge>{
	int start;      //起点
	int end;		//终点
	int distance;  //权
	
	public Edge(){//无参构造函数
	}
	
	public Edge(int start, int end, int distance) {
		super();
		this.start = start;
		this.end = end;
		this.distance = distance;
	}

	@Override
	public int compareTo(Edge o) {
		if(this.distance>o.distance){
			return 1;
		}
		if(this.distance<o.distance){
			return -1;
		}
		return 0;
	}	
}

猜你喜欢

转载自blog.csdn.net/HC199854/article/details/106759608