CCF 201812-4 试题名称:数据中心

具体题目就不贴了。
    不得不说这是一道非常吓人的题。
解题思路:审题有些难度,第一眼看到这道题有些吓人,细细分析(AC )后发现其实不难。题目中希望求出一个最优的树结构传输图,也就是一个最大传输时间最小的树。接下来来看对最大传输时间 T m a x T_{max} Tmax的定义: T m a x T_{max} Tmax是树中每层的最大传输时间的最大值。
khTZ8A.png
结合上面的图可以看出, T m a x = m a x { T 1 , T 2 , T 3 . . . } T_{max}=max{\{T_1,T_2,T_3...\}} Tmax=max{T1,T2,T3...},树的每一层中 T i = m a x { t i , 1 , t i , 2 , t i , 3 , t i , 4 . . . . } T_i=max{\{t_{i,1},t_{i,2},t_{i,3},t_{i,4}....\}} Ti=max{ti,1,ti,2,ti,3,ti,4....},要使得 T m a x T_{max} Tmax最小,也就是要让选入连接各个点的边的传输时间( t i , j t_{i,j} ti,j)的最大值最小,同时要使得整个树的节点都能传输数据到root(可以理解为整个树必须是联通的),此处我认为给出的root没什么用,因为即使root改变了,也就是说将树中的某个子节点看作根节点,它仍然满足树结构,并且树中的边没有变则 T m a x T_{max} Tmax的值就不会改变。
解题步骤:将边按传输时间排序,依次选边,选的过程中注意不能产生环,直到整个树联通,选的最后一条边的传输时间即为 T m a x T_{max} Tmax,也就是扩边法求最小生成树的思路。

100分代码(虽然100分,但是还是很虚,毕竟还是刷了好几年的真题了,还真没见过这样的第四题,思路有什么不对的地方还请各位指正。)

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <sstream>
#include <cstring>
#include <iterator>
#include <set>
#include <map>
using namespace std;
typedef struct edge
{
	int u,v,len;
}edge;

int par[100005];

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

int find(int k)
{
	if(k == par[k])
		return k;
	else
		return par[k] = find(par[k]);
}

bool same(int i,int j)
{
	return find(i) == find(j);
} 

void unite(int i,int j)
{
	i = find(i);
	j = find(j);
	if(i == j)
		return ;
	else	
		par[i] = j;
}

bool cmp(edge& a,edge& b)
{
	return a.len < b.len;
}

int solve(int n,vector<edge>& G)
{
	int ans = 0,cnt = 0;
	init(n);
	int mark[n];
	memset(mark,0,sizeof(mark));
	
	sort(G.begin(),G.end(),cmp);
	
	for(int i = 0;i < G.size(); i++)
	{
		if(!same(G[i].u,G[i].v))
		{
			unite(G[i].v,G[i].u);
			ans = G[i].len;
			if(mark[G[i].u] == 0)
			{
				cnt++;
				mark[G[i].u] = 1;
			}
			if(mark[G[i].v] == 0)
			{
				cnt++;
				mark[G[i].v] = 1;
			}
			if(cnt == n)
				return ans;
		}
	}
	
	return ans;
}

int main(int argc, char const *argv[])
{
	int n,m,root; 
	cin >> n >> m;
	vector<edge> G(m);
	cin >> root;

	for(int i = 0;i < m; i++)
		cin >> G[i].u >> G[i].v >> G[i].len;
	
	cout << solve(n,G) << endl;
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值