UVA 1395 Slim Span 最小生成树

题意:

    给你一个图,让你求这个图中所有生成树中满足题目条件的,这个条件是生成树中最长边与最短边的差值最小。


思路:

               根据最小瓶颈生成树的定义:在一个有权值的无向图中,求一个生成树最大边的权值尽量小。首先以K算法做这道题,先给所有边排好序,然后我可以从小到大枚举每一条边作为我所求生成树的最短边(即第一次以最短边求最小生成树,第二次删除第一条边,以第二条边为最短边求最小生成树,第三次删除第一条边和第二条边,以第三边为最短边求最小生成树。)然后在这个过程中更新   MST(maxE- minE)就好了。这么做的原因是:因为最小生成树一定是无向图的瓶颈生成树。即如果最短边(第一条边)已经定下来,那么最小生成树的 (maxE- minE)一定比其他以这个边为最短边的生成树的(maxE - min E)小。所以就可以依次枚举这个最短边,更新答案就好了。


代码:

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);
		while(true){
			int N,M;
			N = sc.nextInt();
			M = sc.nextInt();
			if(N == 0 && M == 0)break;
			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;
			}
			met(N);
			Arrays.sort(map, 1, M + 1, new mycmp());
			int sst = ksu(N, M, 0);    //SST 初始化为最小生成树的值
			for(int i = 1; i <= M; i++){ //求SST
					met(N);
					int temp = ksu(N, M, i);//以第 i + 1 条边作为第一条边(即删除前i条边后)求MST,如果不等于 -1 说明构造成功
					if(temp < sst && temp != -1){ 
						sst = temp;
				}
			}
			System.out.println(sst);
		}
		sc.close();
	}
	public static int ksu(int N, int M,int mark){  //删除 前 mark 条边 求 MST
		int cnt= 0;
		int st, ed;
		st = ed = map[1].w;
		boolean flag = true;
		for(int i = mark + 1; i <= M; i++){
			int fu = Find(map[i].u);
			int fv = Find(map[i].v);
			if(fu != fv){
				if(flag){
					st = map[i].w;
					flag = false;
				}
				cnt++;
				pre[fv] = fu;
			}
			if(cnt == N - 1){
				ed = map[i].w;
				return ed - st;
			}
		}
		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 met(int N){
		for(int i = 1; i <= N; i++){
			pre[i] = i;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值