算法分析
kruskal
算法的简单变型
去掉的边权最大等价于保留的边权最小,相当于在这个图的每个连通块,求一棵最小生成树,相当于求原图的“最小生成森林”(多棵最小生成树)
res
累加的是需要去掉的边
时间复杂度 $O(mlogm)$
参考文献
算法提高课
Java 代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
static int N = 110, M = 210;
static int n,m;
static Edge[] edge = new Edge[M];
static int[] p = new int[N];
static int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
static int kruskal()
{
int res = 0;
Arrays.sort(edge,0,m);
for(int i = 0;i < m;i ++)
{
int a = edge[i].a;
int b = edge[i].b;
int w = edge[i].w;
a = find(a);
b = find(b);
if(a != b)
{
p[a] = b;
}
else res += w; // 用不上的边加上
}
return res;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] s1 = br.readLine().split(" ");
n = Integer.parseInt(s1[0]);
m = Integer.parseInt(s1[1]);
for(int i = 0;i < m;i ++)
{
String[] s2 = br.readLine().split(" ");
int a = Integer.parseInt(s2[0]);
int b = Integer.parseInt(s2[1]);
int w = Integer.parseInt(s2[2]);
edge[i] = new Edge(a,b,w);
}
for(int i = 1;i <= n;i ++) p[i] = i;
System.out.println(kruskal());
}
}
class Edge implements Comparable<Edge>
{
int a,b,w;
Edge(int a,int b,int w)
{
this.a = a;
this.b = b;
this.w = w;
}
@Override
public int compareTo(Edge o) {
// TODO 自动生成的方法存根
return Integer.compare(w, o.w);
}
}