传送门:
P1111 修复公路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
https://www.luogu.com.cn/problem/P1111
问题分析
读完题不难发现,这题可以用标准的并查集去做,最大的难点是如何对数据进行排序,我们需要将修路的时间从小到大排好。这里我用的是map,Map<int[],Integer>。(这里注意,不能将Integer最为键,如Map<Integer,int[]>,因为键是唯一不同重复的,而不同村庄之间公路修筑时间t可能相等)那么如何对Map的值排序呢,直接给代码:
List<Map.Entry<int[],Integer>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<int[], Integer>>() {
@Override//这里用到了匿名内部类
public int compare(Map.Entry<int[], Integer> o1, Map.Entry<int[], Integer> o2) {
return o1.getValue()-o2.getValue();
}
});
AC代码
import java.io.*;
import java.util.*;
public class Main {
static int[] fa;
static int[] rank;
static Map<int[],Integer> map = new HashMap<>();
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(br);//当然用Scanner一样的
//数据输入
st.nextToken();int n = (int)st.nval;
st.nextToken();int m = (int)st.nval;
fa = new int[n+1];rank = new int[n+1];//数组初始化
for(int i=1;i<=m;i++){
st.nextToken();int x = (int)st.nval;
st.nextToken();int y = (int)st.nval;
st.nextToken();int t = (int)st.nval;
map.put(new int[]{x,y},t);
}
//匿名内部类Collections排序
List<Map.Entry<int[],Integer>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<int[], Integer>>() {
@Override
public int compare(Map.Entry<int[], Integer> o1, Map.Entry<int[], Integer> o2) {
return o1.getValue()-o2.getValue();
}
});
init(n);//初始化
int ans = -1;
for(Map.Entry<int[],Integer> entry : list){
int[] k = entry.getKey();
int x = k[0];
int y = k[1];
merge(x,y);
if(isOver(n)) {//如果任意两个村庄都能通车,则跳出循环,输出最小时间
ans = entry.getValue();
break;
}
}
System.out.println(ans);
}
static void init(int n){
for(int i=1;i<=n;i++){
fa[i] = i;
rank[i] = 1;
}
}
static int find(int k){
if(fa[k] == k){
return k;
} else {
fa[k] = find(fa[k]);
return fa[k];
}
}
static void merge(int i,int j){
int x = find(i),y = find(j);
if(rank[x] >= rank[y]){
fa[y] = x;
} else {
fa[x] = y;
}
if(rank[x] == rank[y]&&x!=y){
rank[x]++;
}
}
static boolean isOver(int n){//该方法用于检测任意两个村庄是否连通
int x,y;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
x = find(i);y = find(j);
if(x!=y) return false;
}
}
return true;
}
}
本文解析了如何使用并查集解决洛谷竞赛中的公路修复问题,重点介绍了如何利用Map数据结构对修路时间进行排序,以便高效解决问题。通过匿名内部类实现Comparator进行排序,确保代码AC通过。
505

被折叠的 条评论
为什么被折叠?



