SDU程序设计思维Week6-作业 D-数据中心

SDU程序设计思维Week6-作业

D-数据中心

Description

存在一个n节点的无向网络图,编号从1到n,现在每个节点需要选择一条路径将数据发送到root号节点。希望求出一个最优的树结构传输图,使得完成任务所需要的传输时间最少。
一个树结构的传输时间为Tmax,其中Tmax=max(Th),h为接收点在树中的深度,Th=max(th,j),th,j表示j条不同的边,这j条边接收点的深度都为h。
输入节点数n(n<=5x10e4)、边数m(m<=10e5)、root节点(root<=5x10e4),接下来输入每条边的两个顶点v、u和传输时间t(v<=5x10e4,u<=5x10e4,t<=10e6)
要求输出正整数ans,表示最优的树结构流水线所耗时Tmax

Sample

Input:
4
5
1
1 2 3
1 3 4
1 4 5
2 3 8
3 4 2

Output:
4

在这里插入图片描述

Idea

由题可知给定无向图,求解一棵生成树,使得最大边权最小,最小生成树一定是瓶颈生成树(即树中最大边权是所有生成树的最大边权中的最小值),所以问题转化为求最小生成树中耗时最大的那条边的边权。利用与C题相似的思想,用edge结构数组存储边,按边权升序排序,在Kruskal求最小生成树中利用并查集对边进行合并。对每条边的两个顶点来说,如果二者在同一并查集中表明二者已经在最小生成树,放弃该边,如果二者不在同一并查集中,则将二点合并,即把边加入生成树中,同时把ans和边权比较取最大值(记录最小生成树中的最大边权)。直至最小生成树包含n个节点后此时的ans就是所求的最优的树结构流水线所耗时Tmax

Summary

这题与C题类似,思想也是Kruskal+并查集。区别在于Kruskal加边的过程中要定义一个变量存储当前树的最大边权
这道题难在理解题意,求解最优树结构流水线所耗时间Tmax→所有生成树对应的最大边权中的最小值→瓶颈生成树的最大边权→最小生成树的最大边权。

Codes

#include <iostream>
#include <algorithm>
using namespace std;
int n, m,root,ans=0,v,u,t,tot=0,num=1;
int par[50050];
struct edge {
	int u, v, w;

}e[100050];

bool operator<(edge &x, edge &y) {
	return x.w < y.w;
}

void init(int n) {
	for (int i = 1; i <= n ; i++)
		par[i] = i;
}

int find(int x) {
	return par[x] == x ? x : par[x] = find(par[x]);
}
void uni(int x, int y) {
	x = find(x);
	y = find(y);
	if (x != y)par[x] = y;
}

int main()
{
	cin.sync_with_stdio(false);
	cin >> n >> m >> root;
	for (int i = 0; i < m; i++) {
		cin >> v >> u >> t;
		e[tot].u = u;
		e[tot].v = v;
		e[tot].w = t;
		tot++;
	}
	init(n);
	sort(e, e + tot);
	for (int i = 0; i < tot; i++) {
		if (find(e[i].u) != find(e[i].v)) {
			uni(e[i].u, e[i].v);
			ans = max(ans, e[i].w);
			num++;
		}
		if (num == n)break;
	}
	printf("%d\n", ans);

}


发布了21 篇原创文章 · 获赞 5 · 访问量 764

猜你喜欢

转载自blog.csdn.net/weixin_44578615/article/details/105125139