数据中心 100分 CCF 201812-4 [最小生成树 + 优先队列] Java版本
样例输入
4
5
1
1 2 3
1 3 4
1 4 5
2 3 8
3 4 2
样例输出
4
样例说明
思路:
这个题我是用Java解决的
主要是求最小生成树上权值最小的那个边,
最终用了克鲁思卡尔(Kraskra) + 优先队列
终于在不超时的情况下满分了
说下要注意的地方
- 感觉CCF中,Java很容易超时。
- 首先观察给出的数据量大小,发现是一个比较稀疏的图,所以用 Kraskra求最小生成树比较好一点。
- 然后发现一直是90分显示超时,没办法把 Kraskra中给所有边排序的过程改成了用优先队列,终于不超时了。
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
final static int INF = Integer.MAX_VALUE >> 1;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m, n, r;
n = in.nextInt();
m = in.nextInt();
r = in.nextInt() - 1;
int v, u, t;
PriorityQueue<int[]> graph = new PriorityQueue<int[]>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[2] - o2[2];
}
});
for (int i = 0; i < m; ++i) {
int node[] = new int[3];
node[0] = in.nextInt() - 1;
node[1] = in.nextInt() - 1;
node[2] = in.nextInt();
graph.add(node);
}
int ans = kruskal(graph, n, r);
System.out.println(ans >= 0 ? ans : 0);
}
static int father[];
static int findFather (int x) {
int a = x;
while ( x != father[x]) {
x = father[x];
}
while ( a != father[a]) {
int tmp = a;
a = father[a];
father[tmp] = x;
}
return x;
}
static public int kruskal (PriorityQueue<int[]> g, int n, int s) {
int ans = 0, eNum = 0;
father =new int[n];
for (int i = 0; i < n; ++i){
father[i] = i;
}
while(!g.isEmpty()) {
int[] node = g.poll();
int fU = findFather(node[0]);
int fV = findFather(node[1]);
if (fU != fV) {
father[fU] = fV;
ans = Math.max(ans, node[2]);
eNum ++;
if (eNum == n - 1) break; // 达到全职
}
}
return ans;
}
}