题目链接:http://acm.fzu.edu.cn/problem.php?pid=2219
m棵二叉树,表示m个初始工人,每一次分叉都是使用魔法将一个工人变成两个工人,因为每次需要k单位的时间,所以我们将每条边的权值设置为k,分叉节点的权值设为0。然后如果这个工人不再进行分裂,而是去做建造第i个建筑,它的下方就直接接一个权值为t[i]的节点。为了说明的方便,我们引入一个虚的根节点,从根节点往这m棵树的树根每个都引一条权值为0的边。
就这样分裂,直到有n个叶子节点,此时把建筑所需的时间往叶子节点里放,如何放使所有叶子节点到虚的根节点的权值和的最大值最小。
我们的策略就是把建筑时间小的放在树的高度最高的,依次这样。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<functional>
using namespace std;
priority_queue<int, vector<int>, greater<int> > pq;
int t;
int n, m, k;
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &n, &m, &k);
int x;
for (int i = 0; i < n; i++)
{
scanf("%d", &x);
pq.push(x);
}
while (n>m)
{
pq.pop();
pq.push(pq.top() + k);
pq.pop();
n--;
}
int num = pq.size();
while (num > 1)
{
pq.pop();
num--;
}
cout << pq.top() << endl;
pq.pop();
}
return 0;
}