用java编写假设你是电信工程师,需要为村庄间架设通信网络,使任何两个村庄间都可以实现通信连通(但不一定有直接的快速线路相连,只要互相间接有线路连通即可)。现有规划信息数据,列出了所有可能架设线路的两个村庄及其线路成本,请判断是否可以实现村村互联,如果可以,整个网络的最低成本是多少?如果不能实现村村互联,分成几个部分,各部分有哪些村庄? 输入格式: 第一行给出村庄数目n (1≤n≤50)和候选线路条数m≥0;随后的m行,每行给出3个正整数,分别是该条线路直接连通的两个村庄的编号(编号从1开始起编)以及该线路的建设成本。 输出格式: 输出是否实现村村互联的判断结果。 如果是,再输出整个网络的最低成本。 如果不能实现互联,输出分成几部分,每部分有哪些村庄。每个不连通部分的中的顶点是从小到大 。各部分的前后顺序也是按第一个顶点从小到大列出。
时间: 2024-03-09 14:45:37 浏览: 98
通信网络的设计问题
5星 · 资源好评率100%
以下是Java代码实现:
```java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class VillageNetwork {
static class Edge implements Comparable<Edge> {
int from, to, weight;
public Edge(int from, int to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
@Override
public int compareTo(Edge o) {
return this.weight - o.weight;
}
}
private static int[] father;
private static int find(int x) {
if (father[x] != x) {
father[x] = find(father[x]);
}
return father[x];
}
private static void union(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx != fy) {
father[fx] = fy;
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int m = input.nextInt();
father = new int[n + 1];
for (int i = 1; i <= n; i++) {
father[i] = i;
}
ArrayList<Edge> edges = new ArrayList<>();
for (int i = 0; i < m; i++) {
int a = input.nextInt();
int b = input.nextInt();
int c = input.nextInt();
edges.add(new Edge(a, b, c));
}
// Kruskal 算法求最小生成树
int cost = 0;
ArrayList<Integer>[] parts = new ArrayList[n + 1];
for (int i = 1; i <= n; i++) {
parts[i] = new ArrayList<>();
parts[i].add(i);
}
int cnt = 0;
edges.sort(Edge::compareTo);
for (Edge edge : edges) {
int a = edge.from;
int b = edge.to;
int c = edge.weight;
if (find(a) != find(b)) {
union(a, b);
cost += c;
parts[find(a)].addAll(parts[find(b)]);
cnt++;
}
if (cnt == n - 1) {
break;
}
}
if (cnt == n - 1) {
System.out.println("Yes");
System.out.println(cost);
} else {
System.out.println("No");
int num = n - cnt;
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
for (int i = 1; i <= n; i++) {
if (find(i) == i) {
res.add(parts[i]);
}
}
res.sort((list1, list2) -> list1.get(0) - list2.get(0));
for (int i = 0; i < num; i++) {
ArrayList<Integer> part = res.get(i);
System.out.print(part.get(0));
for (int j = 1; j < part.size(); j++) {
System.out.print(" " + part.get(j));
}
System.out.println();
}
}
}
}
```
首先,我们定义了一个静态内部类 Edge,表示一条边,包含起点、终点和权值。然后,我们读入村庄数目和候选线路条数,以及每条线路的信息,并将它们存储在一个 ArrayList 中。接着,我们使用 Kruskal 算法求出最小生成树的权值和,并判断是否实现了村村互联。如果是,我们输出整个网络的最低成本。如果不能实现互联,我们输出分成几部分,每部分有哪些村庄,并按第一个顶点从小到大列出。
时间复杂度为 O(m log m),其中 m 为候选线路条数。
阅读全文