题意:
给你点和边,求出最小生成树 和 次小生成树。
思路:
先求一次最小生成树,然后标记每一条边,依次删除,再求最小生成树,从中找到最小的就是次小生成树了。
代码:
import java.util.Scanner;
import java.util.Comparator;
import java.util.Arrays;
class Node{
public int u, v, w, mark;
}
//结构排序
class mycmp implements Comparator<Node>{
public int compare(Node A, Node B){
return A.w - B.w;
}
}
public class Main {
final static int MAXN = 10000 + 13;
final static int INF = 0x3f3f3f3f;
static int[] pre = new int[MAXN];
static Node[] map = new Node[MAXN];
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while(T != 0){
int N,M;
N = sc.nextInt();
M = sc.nextInt();
for(int i = 1; i <= M; i++){
map[i]=new Node();
map[i].u = sc.nextInt();
map[i].v = sc.nextInt();
map[i].w = sc.nextInt();
map[i].mark = 0;
}
mst(N);
Arrays.sort(map, 1, M + 1, new mycmp());
int mst = ksu(N, M); // MST
int sst = INF + 1; //SST 初始化
for(int i = 1; i <= M; i++){ //求SST
if(map[i].mark == 1){ //这条边属于MST
mst(N);
int temp = ksu(N, M, i); //删除一条边后得到的结果、如果大于 0 说明构造成功,否则构造失败
if(temp < sst && temp != -1){
sst = temp;
}
}
}
System.out.println(mst + " " + sst);
T--;
}
sc.close();
}
public static int ksu(int N, int M){ //求MST
int cnt = 0;
int ans= 0;
for(int i = 1; i <= M; i++){
int fu = Find(map[i].u);
int fv = Find(map[i].v);
if(fu != fv){
ans += map[i].w;
cnt++;
pre[fv] = fu;
map[i].mark = 1; //标记
}
if(cnt == N - 1){
return ans;
}
}
return ans;
}
public static int ksu(int N, int M,int mark){ //删除 mark 这条边 求 MST
int ans= 0;
int cnt = 0;
for(int i = 1; i <= M; i++){
if(i == mark) continue; //删除
int fu = Find(map[i].u);
int fv = Find(map[i].v);
if(fu != fv){
ans += map[i].w;
cnt++;
pre[fv] = fu;
}
if(cnt == N - 1){
return ans;
}
}
return -1;
}
public static int Find(int x){
return x == pre[x] ? x : (pre[x] = Find(pre[x]));
}
public static void debug(int M){
for(int i = 1; i <= M; i++){
System.out.println(i + " " + map[i].u + " " + map[i].v + " " + map [i].w + " "+ map[i].mark);
}
}
public static void mst(int N){
for(int i = 1; i <= N; i++){
pre[i] = i;
}
}
}