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);
}