试题编号: | 201812-4 |
试题名称: | 数据中心 |
时间限制: | 1.0s |
内存限制: | 512.0MB |
问题描述: | 样例输入 4 样例输出 4 样例说明 下图是样例说明。 |
试题分析
这个题目最麻烦的地方显然是读不懂题。圈重点:1.根据网络的定义,每个节点可以接受多个节点的信息,但是每个节点不能向多个节点发送信息,因此这个网络图应该是一棵树。2. 要求传输时间最短,因此这棵树的每条边权重之和应该是最小的。 3. 读懂Tmax的定义,其实就是这棵最小生成树的最大边的权重。
综上所述,我们要求的就是给定图的最小生成树的最大边的权重。
说到这里,题目的解法就很明确了。解决最小生成树问题常用的两种算法是Prim算法和Kruskal算法,在这里采用Kruskal算法解决这个问题。
1. 将所有边的权重按照从小到大进行排序。
2. 按照从小到大的顺序使用上述边连接对应的节点,前提是这些边不能形成回路,如果形成回路,则需要跳过这条边。
3. 假设有n个节点,输出第n-1个被加入的边的权重,这也就是最小生成树的最大边的权重。
在判断加入的边是否会形成回路方面,使用并查集算法来做这项任务,有关并查集的教程可以在coursera上学习普林斯顿的算法课程,本文中的代码使用的就是普林斯顿的课程提供的并查集代码。
代码
这份代码在CCF的评测系统上有的时候是100,有的时候会导致运行超时。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
public class Main {
public class WeightedQuickUnionUF {
private int[] parent;
private int[] size;
public WeightedQuickUnionUF(int n) {
parent = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
size[i] = 1;
}
}
public int find(int p) {
while (p != parent[p])
p = parent[p];
return p;
}
public boolean connected(int p, int q) {
return find(p) == find(q);
}
public void union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ) return;
if (size[rootP] < size[rootQ]) {
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
else {
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
}
}
}
class Vertex2Vertex implements Comparable<Vertex2Vertex>{
public int vertex1;
public int vertex2;
public int weight;
public Vertex2Vertex(int vertex1, int vertex2, int weight) {
this.vertex1 = vertex1;
this.vertex2 = vertex2;
this.weight = weight;
}
@Override
public int compareTo(Vertex2Vertex o) {
if(this.weight>o.weight){
return 1;
}
else{
return -1;
}
}
}
public void run(){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
in.nextInt();
WeightedQuickUnionUF uf = new WeightedQuickUnionUF(n);
Vertex2Vertex[] elements = new Vertex2Vertex[m];
for(int i=0;i<m;i++){
int vertex1 = in.nextInt()-1;
int vertex2 = in.nextInt()-1;
int weight = in.nextInt();
elements[i] = new Vertex2Vertex(vertex1,vertex2,weight);
}
Arrays.sort(elements);
int max_weight = 0;
int counter = 0;
for(Vertex2Vertex e:elements){
if(counter==n-1)
break;
if(!uf.connected(e.vertex1,e.vertex2)){
uf.union(e.vertex1,e.vertex2);
counter+=1;
if(e.weight>max_weight){
max_weight=e.weight;
}
}
}
System.out.print(max_weight);
}
public static void main(String[] args) {
new Main().run();
}
}