POJ 1679 The Unique MST 次小生成树

题意:

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

代码:

  1 /*
  2     POJ 1679:判断最小生成树是否唯一
  3     思路:先求出最小生生成树 MST,再求出次小生成树SST,判断是否相等。
  4     求SST:先求最小生成树,标记构成最小生成树的每一条边,然后依次删除,再次求最小生成树,取这里面的最小的即是次小生成树
  5     算法实现:kruskal 
  6     错误:删除一条属于MST的边时,应该考虑到,有可能构造不成生成树了,所以有必要返回 -1 判断下(WA了好几次)。
  7 */
  8 import java.util.Scanner;
  9 import java.util.Comparator;
 10 import java.util.Arrays;
 11 
 12 class Node{
 13     public int u, v, w, mark;
 14 }
 15 //结构排序
 16 class mycmp implements  Comparator<Node>{
 17     public int compare(Node A, Node B){ 
 18                 return A.w - B.w;  
 19       }  
 20 }
 21 public class Main {
 22     final static int MAXN = 10000 + 13;
 23     final static int INF = 0x3f3f3f3f;
 24     static int[] pre = new int[MAXN];
 25     static Node[] map = new Node[MAXN];
 26     public static void main(String[] args){
 27         Scanner sc = new Scanner(System.in);
 28         int T = sc.nextInt();
 29         while(T != 0){
 30             int N,M;
 31             N = sc.nextInt();
 32             M = sc.nextInt();
 33             for(int i = 1; i <= M; i++){
 34                 map[i]=new Node();  
 35                 map[i].u = sc.nextInt();
 36                 map[i].v = sc.nextInt();
 37                 map[i].w = sc.nextInt();
 38                 map[i].mark = 0;
 39             }
 40             mst(N);
 41             Arrays.sort(map, 1, M + 1, new mycmp());
 42             int mst = ksu(N, M);   // MST
 43             int sst = INF + 1;    //SST 初始化
 44             for(int i = 1; i <= M; i++){ //求SST
 45                 if(map[i].mark == 1){  //这条边属于MST
 46                     mst(N);
 47                     int temp = ksu(N, M, i);       //删除一条边后得到的结果、如果大于 0 说明构造成功,否则构造失败
 48                     if(temp < sst && temp != -1){ 
 49                         sst = temp;
 50                     }
 51                 }
 52             }
 53             if(sst == mst){
 54                 System.out.println("Not Unique!");
 55             }
 56             else{
 57                 System.out.println(mst);
 58             }
 59             T--;
 60         }
 61         sc.close();
 62     }
 63     public static int ksu(int N, int M){ //求MST
 64         int cnt = 0;
 65         int ans= 0;
 66         for(int i = 1; i <= M; i++){
 67             int fu = Find(map[i].u);
 68             int fv = Find(map[i].v);
 69             if(fu != fv){
 70                 ans += map[i].w;
 71                 cnt++;
 72                 pre[fv] = fu;
 73                 map[i].mark = 1;   //标记
 74             }
 75             if(cnt == N - 1){
 76                 return ans;
 77             }
 78         }
 79         return ans;
 80     }
 81     public static int ksu(int N, int M,int mark){  //删除 mark 这条边 求 MST
 82         int ans= 0;
 83         int cnt = 0;
 84         for(int i = 1; i <= M; i++){
 85             if(i == mark) continue;    //删除
 86             int fu = Find(map[i].u);
 87             int fv = Find(map[i].v);
 88             if(fu != fv){
 89                 ans += map[i].w;
 90                 cnt++;
 91                 pre[fv] = fu;
 92             }
 93             if(cnt == N - 1){
 94                 return ans;
 95             }
 96         }
 97         return -1;//说明无法再生成最小生成树
 98     }
 99     public static int Find(int x){
100         return x == pre[x] ? x : (pre[x] = Find(pre[x]));
101     }
102     public static void debug(int M){
103         for(int i = 1; i <= M; i++){
104             System.out.println(i + " " + map[i].u + " " + map[i].v + " " + map [i].w + " "+ map[i].mark);
105         }
106     }
107     public static void mst(int N){
108         for(int i = 1; i <= N; i++){
109             pre[i] = i;
110         }
111     }
112 }

 

 

 
 

 

转载于:https://www.cnblogs.com/Ash-ly/p/5397640.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值