题意:
判断最小生成树是不是唯一,我的判断方法是求次小生成树,如果相等那么说明不唯一。
代码:
/*
POJ 1679:判断最小生成树是否唯一
思路:先求出最小生生成树 MST,再求出次小生成树SST,判断是否相等。
求SST:先求最小生成树,标记构成最小生成树的每一条边,然后依次删除,再次求最小生成树,取这里面的最小的即是次小生成树
算法实现:kruskal
错误:删除一条属于MST的边时,应该考虑到,有可能构造不成生成树了,所以有必要返回 -1 判断下(WA了好几次)。
*/
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;
}
}
}
if(sst == mst){
System.out.println("Not Unique!");
}
else{
System.out.println(mst);
}
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;
}
}
}