首页 > 网易笔试8.8(生成树最大权值与最小权值之差最小)
头像
little_luck
编辑于 2020-08-10 16:29
+ 关注

网易笔试8.8(生成树最大权值与最小权值之差最小)

#include <bits/stdc++.h>

using namespace std;

struct Edge{
	int u, v;
	int w;
};

bool inSameSet(int *uni, int r1, int r2) {
	while(r1 != uni[r1]) r1 = uni[r1];
	while(r2 != uni[r2]) r2 = uni[r2];
	
	if(r1 == r2) return true;
	uni[r1] = r2;
	return false;
}

int solution() {
	int n, m;
	cin >> n >> m;
	
	//顶点为1时,边数自然为0 
	if(n == 1) 
		return 0;	
	
	int uni[n+1];
	for(int i = 1; i<=n; ++i) uni[i] = i;
	
	Edge edge[m];
	for(int i = 0; i<m; ++i) {
		cin >> edge[i].u >> edge[i].v >> edge[i].w; 
	}
	
	sort(edge, edge+m, [](Edge& a, Edge& b) {
		return a.w < b.w;
	});
	
	int l, r, dw = n-2, min_d = INT_MAX;
	for(int i = dw; i<m; ++i) {
		if(edge[i].w - edge[i-dw].w < min_d) {
			r = i;
			min_d = edge[i].w - edge[i-dw].w;
		}
	}
	
	l = r-dw;
	
	//先加l, l+1, ..., r这n-1条边,看是否构成树
	int cnt = 0;	//加入的边数 
	for(int i = l; i<=r; ++i) {
		if(!inSameSet(uni, edge[i].u, edge[i].v)) {
			++cnt;
		}
	}	
	
	//若边数cnt小于n-1则还得往两边去找边加入到集合中,直到找到n-1条边 
	while(l >= 0 && r<n && cnt < n-1) {
		if(l == 0) {
			++r;
			if(r<n && !inSameSet(uni, edge[r].u, edge[r].v)) {
				++cnt;
			}
		} else if(r == n-1) {
			--l;
			if(l>=0 && !inSameSet(uni, edge[l].u, edge[l].v)) {
				++cnt;
			}
		} else {
			
			if(edge[r].w - edge[l-1].w < edge[r+1].w -edge[l].w) {
				--l;
				if(!inSameSet(uni, edge[l].u, edge[l].v)) ++cnt;
			} else{
				++r;
				if(!inSameSet(uni, edge[r].u, edge[r].v)) ++cnt;
			}
		}
	}
	
	return edge[r].w - edge[l].w;
}

int main()
{
	cout << solution() << endl;
	return 0;
 } 

题目描述:有一张n个顶点m条边的无向图,每条边一个权值。
牛牛希望构造一棵生成树(既保留n-1条边,单保持图连通),使得最大边权减去最小边权的值最小。

输入:2 1
1 2 100
输出: 0
解释:第一行为该图顶点数为n = 2,边数 m = 1,后面的m行为边的信息,1 2 100 表示边(1, 2)的权值为100

全部评论

(1) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

历年真题 真题热练榜 24小时
技术(软件)/信息技术类
查看全部

近期精华帖

热门推荐