测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。 当N为0时输入结束。
每个测试用例的输出占一行,输出全省畅通需要的最低成本。
链接:https://www.nowcoder.com/questionTerminal/16212f7d46e44174b5505997ea998538 来源:牛客网 import java.util.Scanner; import java.util.Arrays; import java.util.Comparator; class edge{ private int u; private int v; private int w; public edge(int u, int v, int w) { this.u = u; this.v = v; this.w = w; } public int getU() { return u; } public int getV() { return v; } public int getW() { return w; } public void setW(int w){ this.w = w; } } public class Main { static int f[] = new int[100]; public static void main(String[] args) { Scanner input=new Scanner(System.in); int n = input.nextInt(); //顶点数 int m = n*(n-1)/2; //边数 edge e[] = new edge[m]; for(int i=0;i<m;i++){ int u = input.nextInt(); int v = input.nextInt(); int w = input.nextInt(); e[i] = new edge(u,v,w); int status = input.nextInt(); if(status == 1){ e[i].setW(0); } } //按边的权值从小到大排序 Arrays.sort(e, new Comparator<edge>(){ public int compare(edge o1, edge o2) { if(o1.getW()>o2.getW()){ return 1; }else if(o1.getW()<o2.getW()){ return -1; }else{ return 0; } } }); //并查集初始化,数组里存的是自己数组的下标编号 for(int i=0;i<n;i++){ f[i] = i; } //Kruskal算法核心部分 int count = 0,sum = 0; for(int i=0;i<m;i++){ //从小到大枚举每一条边 if(merge(e[i].getU(),e[i].getV())){ //判断两个点是否联通,不连通则用这条边 count++; sum += e[i].getW(); } if(count == n-1){ break; } } System.out.println(sum); } //并查集合并两个子集合 public static boolean merge(int u,int v){ int t1 = getf(u); int t2 = getf(v); if(t1 != t2){ //判断两个点是否在同一个集合中 f[t2] = t1; return true; } return false; } //并查集寻找祖先 public static int getf(int v){ if(f[v]==v){ return v; }else{ f[v] = getf(f[v]); //路径压缩 return f[v]; } } }
原文:https://www.cnblogs.com/JAYPARK/p/10371339.html