Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
给定一个 nn 个点 mm 条边的无向图,图中可能存在重边和自环,边权可能为负数。求最小生成树的树边权重之和,如果最小生成树不存在则输出
impossible。给定一张边带权的无向图 G=(V,E)G=(V,E),其中 VV 表示图中点的集合,EE 表示图中边的集合,n=|V|n=|V|,m=|E|m=|E|。
由 VV 中的全部 nn 个顶点和 EE 中 n−1n−1 条边构成的无向连通子图被称为 GG 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 GG 的最小生成树。
输入格式
第一行包含两个整数 nn 和 mm。
接下来 mm 行,每行包含三个整数 u,v,wu,v,w,表示点 uu 和点 vv 之间存在一条权值为 ww 的边。
输出格式
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出
impossible。数据范围
1≤n≤5001≤n≤500, 1≤m≤1051≤m≤105, 图中涉及边的边权的绝对值均不超过 1000010000。
输入样例:
4 5 1 2 1 1 3 2 1 4 3 2 3 2 3 4 4输出样例:
6
二、思路分析:
这里我们可以看到图为稠密图,且算法为求最小生成树算法,像铺路问题之类的都为最小生成树问题的一种。
稠密图 使用prim算法,稀疏图使用kruskal算法。
-
prim算法步骤和Dijkstra算法类似,都是采用贪心的思想。
- 初始化dist数组为正无穷(dist数组为点到生成树集合的距离)
- 迭代 n 次,(Dijkstra算法迭代 n - 1次,因为dijkstra算法一开始已经确定了一个点)
- 每次迭代都找到一个未使用过的离集合最近的点,用这个点来更新其他点离集合最的距离
- 把这个点标志为已使用.
-
- 该题存在重边所以要取重边的最小边放到数组中去
- 该题可能存在负自环所以要先累计权值再更新距离
三、AC 代码:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int n,m;
static boolean st[] = null;
static int[] dist = null;
static int[][] g = null;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt(); m = in.nextInt();
st = new boolean[n+1]; dist = new int[n+1];
g = new int[n+1][n+1];
Arrays.fill(dist, 0x3f3f3f3f);
for (int i = 0; i < n+1; i++) {
Arrays.fill(g[i], 0x3f3f3f3f);
}
for (int i = 0; i < m; i++) {
int a = in.nextInt(); int b = in.nextInt();
// 可能存在重边要取最小值录入
g[a][b] = g[b][a] = Math.min(g[a][b],in.nextInt());
}
int res = Prim();
if(res == 0x3f3f3f3f) System.out.println("impossible");
else System.out.println(res);
}
public static int Prim(){
int res = 0;
for (int i = 0; i < n; i++) {
int t = -1;
for (int j = 1; j < n+1; j++) {
if (!st[j] && (t == -1 || dist[t] > dist [j])) {
t = j;
}
}
// 如果 i 不为 0,且dist[t] 为 正无穷 ,
// 则说明有点不和集合连通,则不能构成最小生成树
if (i > 0 && dist[t] == 0x3f3f3f3f) {
return 0x3f3f3f3f;
}
// 累加权值,i为0则距离还未初始化dist[1]为正无穷
//先累加再更新避免出现负自环的现象
if( i > 0){
res += dist[t];
}
st[t] = true;
// 更新
for (int j = 1; j < n+1; j++) {
dist[j] = Math.min(dist[j], g[t][j]);
}
}
return res;
}
}