POJ 1679 The Unique MST 次小生成树

题意:

                 判断最小生成树是不是唯一,我的判断方法是求次小生成树,如果相等那么说明不唯一。


代码:

/*
	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;
		}
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值