最小生成树

朴素prim
- 时间复杂度是 O(n^2^+m),n表示点数,m表示边数
- 适用于稠密图

int n;
int g[N][N];
int dist[N];
bool st[N];
int prim()
{
memset(dist, 0x3f, sizeof dist);
int res = 0;
for (int i = 0; i < n; i ++ )
{
int t = -1;
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
if (i && dist[t] == INF) return INF;
if (i) res += dist[t];
st[t] = true;
for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);
}
return res;
}
public static int[][] g = new int[N][N];
public static int[] dist = new int[N];
public static boolean[] st = new boolean[N];
public static int prim() {
Arrays.fill(dist, 0x3f3f3f3f);
int res = 0;
for (int i = 0; i < n; i ++) {
int t = -1;
if (!st[t] && (t == -1 || dist[t] > dist[j])) {
t = j;
}
}
st[t] = true;
if (i != 0 && dist[t] == 0x3f3f3f3f) {
return 0x3f3f3f3f;
}
if (i != 0) {
res += dist[t];
}
for (int j = 1; j <= n; j++) {
dist[j] = Math.min(dist[j], g[t][j]);
}
return res;
}
堆优化版prim
- 时间复杂度O(mlogn)
- 优化方式和用堆优化dijkstra一样
- 不如Kruskal

Kruskal
- 时间复杂度是 O(mlogm), n表示点数,m 表示边数
- 适用于稀疏图

int n, m;
int p[N];
struct Edge
{
int a, b, w;
bool operator< (const Edge &W)const
{
return w < W.w;
}
}edges[M];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int kruskal()
{
sort(edges, edges + m);
for (int i = 1; i <= n; i ++ ) p[i] = i;
int res = 0, cnt = 0;
for (int i = 0; i < m; i ++ )
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a), b = find(b);
if (a != b)
{
p[a] = b;
res += w;
cnt ++ ;
}
}
if (cnt < n - 1) return INF;
return res;
}
public static int[] p = new int[N];
public static Edge[] edges = new Edge[M];
public static class Edge implements Comparable<Pair> {
public int a;
public int b;
public int w;
public Pair(int a, int b, int w) {
this.a = a;
this.b = b;
this.w = w;
}
@Override
public int compareTo(Pair o) {
return this.w - o.w;
}
}
public static int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
public static int kruskal() {
Arrays.sort(edges);
for (int i = 1; i <= n; i++) {
p[i] = i;
}
int res = 0;
int cnt = 0;
for (int i = 0; i < m; i++) {
int a = edges[i].a;
int b = edges[i].b;
int w = edges[i].w;
a = find(a);
b = find(b);
if (a != b) {
p[a] = b;
res += w;
cnt++;
}
}
if (cnt < n - 1) {
return 0x3f3f3f3f;
}
return res;
}
练习
01 Prim算法求最小生成树

import java.io.*;
import java.util.*;
public class Main {
public static final int N = 510;
public static int[][] g = new int[N][N];
public static int[] dist = new int[N];
public static boolean[] st = new boolean[N];
public static int n, m;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
String[] str1 = br.readLine().split(" ");
n = Integer.parseInt(str1[0]);
m = Integer.parseInt(str1[1]);
for (int i = 0; i < N; i++) {
Arrays.fill(g[i], 0x3f3f3f3f);
}
while (m-- > 0) {
String[] str2 = br.readLine().split(" ");
int a = Integer.parseInt(str2[0]);
int b = Integer.parseInt(str2[1]);
int c = Integer.parseInt(str2[2]);
g[a][b] = g[b][a] = Math.min(g[a][b], c);
}
int t = prim();
if (t == 0x3f3f3f3f) {
pw.println("impossible");
} else {
pw.println(t);
}
br.close();
pw.close();
}
public static int prim() {
Arrays.fill(dist, 0x3f3f3f3f);
int res = 0;
for (int i = 0; i < n; i++) {
int t = -1;
for (int j = 1; j <= n; j++) {
if (!st[j] && (t == -1 || dist[t] > dist[j])) {
t = j;
}
}
st[t] = true;
if (i != 0 && dist[t] == 0x3f3f3f3f) {
return 0x3f3f3f3f;
}
if (i != 0) {
res += dist[t];
}
for (int j = 1; j <= n; j++) {
dist[j] = Math.min(dist[j], g[t][j]);
}
}
return res;
}
}
01 Kruskal算法求最小生成树

import java.io.*;
import java.util.*;
public class Main {
public static final int N = 100010;
public static final int M = 200010;
public static int[] p = new int[N];
public static Edge[] edges = new Edge[M];
public static int n, m;
public static class Edge {
public int a;
public int b;
public int w;
public Edge(int a, int b, int w) {
this.a = a;
this.b = b;
this.w = w;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
String[] str1 = br.readLine().split(" ");
n = Integer.parseInt(str1[0]);
m = Integer.parseInt(str1[1]);
for (int i = 0; i < m; i++) {
String[] str2 = br.readLine().split(" ");
int a = Integer.parseInt(str2[0]);
int b = Integer.parseInt(str2[1]);
int c = Integer.parseInt(str2[2]);
edges[i] = new Edge(a, b, c);
}
int t = kruskal();
if (t == 0x3f3f3f3f) {
pw.println("impossible");
} else {
pw.println(t);
}
br.close();
pw.close();
}
public static int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
public static int kruskal() {
Arrays.sort(edges, 0, m, (o1, o2) -> o1.w - o2.w);
for (int i = 1; i <= n; i++) {
p[i] = i;
}
int res = 0;
int cnt = 0;
for (int i = 0; i < m; i++) {
int a = edges[i].a;
int b = edges[i].b;
int w = edges[i].w;
a = find(a);
b = find(b);
if (a != b) {
cnt++;
res += w;
p[a] = b;
}
}
if (cnt < n - 1) {
return 0x3f3f3f3f;
}
return res;
}
}