共有n台服务器,每台服务器可以和若干个子服务器传输数据,n台服务器组成一个树状结构。
现在要将一份数据从root节点开始分发给所有服务器。一次数据传输需要一个小时时间,
一个节点可以同时对k个儿子节点进行并行传输,不同节点可以并行分发。
问,全部分发完成,最短需要多少小时?
【示例】:
当共有5台服务器,其树状结构为
0
/ \
1 2
/ \
3 4
假设每一台服务器同时可以对1个儿子节点(k=1)并行传输,最优的数据传输过程示例如下:
第一个小时,0 -> 1;
第二个小时,1->3 & 0->2;
第三个小时,1 -> 4;
所以当k=1时,全部分发完成最短需要3个小时。
假设每一台服务器同时可以对2个儿子节点(k=2)并行传输,最优的数据传输过程示例如下:
第一个小时,0 -> 1 & 0 -> 2;
第二个小时,1 -> 3 & 1 -> 4;
所以当k=2时,全部分发完成最短需要2个小时。
【常规思路】
构建出树的描述:
即:
vector<int> tree[500000]; 其中 tree[i]存放i节点的所有子节点
基本策略为:
一个根节点开始的子树最终分发时间取决于其子节点的情况:
如果没子节点:那么当前树木(只有一个节点)分发完的时间为0
如果有子节点:那么其分发完的时间是,将所有子树单独分发完时间进行排序。
第一组k个的分发时间是:根节点分发到自己1个时间+自己单独到所有子结构时间 即可完成那些方向的所有分发任务。
第二组k个的分发时间是:先等待第一组分发完毕1个单位时间+自己单独分发子结构时间+根节点分发到自己1个单位时间。
......
#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;const int MAX_V=1000005;
//用于存储树
vector<int> tree[MAX_V];
int cmp(int a,int b){return a>b;
}
int k;
int get_result(int root){// 如果当前节点没有孩子,即使叶子节点,那么它就不需要分发,直接返回0if (tree[root].empty()){return 0;}//用于存储每个孩子节点分发完的时间vector<int>tres;for (int v : tree[root]) {tres.push_back(get_result(v));}// 计算root节点的分发时间// root分发的时候,先发给,那些分发完所需时间最长的子节点sort(tres.begin(),tres.end(),cmp);int ares=0;for (int i = 0; i <tres.size() ; ++i) {tres[i]=tres[i]+floor(i*1.0/k)+1; //不同组分发 需要等待前面先分发完ares=max(ares,tres[i]);}return ares;}
int main(){int row_num,num,parent,child;//输入cin>>k>>row_num;for (int i = 0; i <row_num ; ++i) {cin>>num>>parent;for (int j = 0; j <num-1 ; ++j) {cin>>child;tree[parent].push_back(child);}}//计算根结点的最短分发时间cout<<get_result(0);return 0;
}