算法分析
普通的最小生成树:所有边权之和最小
本题的最小生成树:最大的边权最小
在这里我深刻的意识到kruskal
本质是让点按照某个规律进行连通,res
是特有的属性
做法:kruskal
-
1、将所有边从小到大排序
-
2、枚举每条边
a
,b
,权值是w
- if
a
和b
不连通,将a
,b
加进集合,且更新res
- if
时间复杂度 $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 = 310, M = 10010;
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;
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(n - 1 + " " + 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);
}
}