标签:
作为一个电子商务为主体的公司,京东一直努力实现自己“多、快、好、省”的承诺。其中,“快”的特质更是被京东发挥到了极致。京东建立了一个非常高效的物流网络,物流网络构成了一个树结构,由很多的物流点和将物流点连结起来的道路组成。
京东物流网络中每个物流点有一个权值 di,物流点间的道路也都有一个权值 wi。对于一条物流网络中的路径,令路径上所有物流点权值 di 的最小值为 mind,路径上所有道路权值 wi 的总和为 sumw,则该条路径的总权值为 mind * sumw。路径的起点和终点可以是物流网络中的任意物流点,且路径中不能出现重复的物流点。
请求出京东的这个树形物流网络所有路径总权值中的最大值。
输入格式
第一行输入一个整数 T(1 ≤ T ≤ 50),表示数据组数。
每组数据第一行一个整数 n(1 ≤ n ≤ 105),表示有 n 个物流点。
之后一行 n 个整数,表示每个物流点的权重 di(1 ≤ di ≤ 109)。
接下来有 n - 1 行,每行 3 个整数 ui,vi,wi(1 ≤ ui, vi ≤ n, 1 ≤ wi ≤ 109),表示有一条连接 ui 和 vi 的权值为 wi 的道路。输入数据保证没有重复出现的(ui,vi)点对,且最终一定会形成一个树形物流网络。
最多有 10 组数据的 n 超过 104。
输出格式
一共输出 T 行,每行一个整数,表示路径总权值的最大值。
输入:
1 3 1 2 3 1 2 1 1 3 2
输出:
3
总权值最大的路径是 2 - 1 - 3,mind 为 min(1, 2, 3) = 1,sumw 为 sum(1, 2) = 3,因此总权值为 1 * 3 = 3。
第一步:深度优先遍历整棵树,对于子树选择子树的重心作为子树的root节点继续递归
第二步:深度优先遍历每个子树,考虑所有的分支节点到root节点之间的路径长度sumw和路径最小点权mind和相对于root的子树分支编号id,用stk[]数组保存三个变量。
第三步:将stk[]数组中按mind从大到小排序,依次考虑每一条终点为root节点的路径,合并id编号不同的两条路径(root即为中间节点),保留考虑过的路径中路径长度最长的路径path1,和与path1路径不同id号的次长路径path2(这样不至于两个最长路径(id号相同)合并时出现路径重合情况,解决方案是和path2合并路径)
注:第三步做法的依据是先从mind大号枚举路径考虑到mind较小节点时,我们最想和此路径(mind较小点所在路径)和并的路径是之前考虑过的路径中路径最长的路径。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define N 210000 #define LL long long #define inf 0x0f0f0f0f struct Node{ int nxt,val; Node(){} Node(int _n,int _v){ nxt = _n; val = _v; } }; struct STK{ int id,wei; LL len; STK(){} STK(int _id,int _w,LL _l){ id = _id; wei = _w; len = _l; } }; STK stk[N]; vector<Node> nod[N]; int size[N],vis[N],f[N],wgt[N]; int root,top; LL ans; LL max(LL a,LL b){ return a>b?a:b; } LL min(LL a,LL b){ return a<b?a:b; } int Cmp(STK k1,STK k2){ return k1.wei > k2.wei; } void getRoot(int cur,int fa,int sum){ int tmp = 0; size[cur] = 1; for(int i = 0;i<(int)nod[cur].size();i++){ int nxt = nod[cur][i].nxt; if(vis[nxt]||nxt==fa) continue; getRoot(nxt,cur,sum); size[cur] += size[nxt]; tmp = max(tmp,size[nxt]); } f[cur] = max(tmp,sum - size[cur]); if(f[root]>f[cur]) root = cur; } void dfs(int cur,int fa,LL len,int wei,int id){ stk[++top] = STK(id,wei,len); for(int i = 0;i<(int)nod[cur].size();i++){ int nxt = nod[cur][i].nxt; int val = nod[cur][i].val; if(vis[nxt]||nxt==fa) continue; dfs(nxt,cur,len+val,min(wei,wgt[nxt]),id); } } void CDQ(int cur,int sum){ root = 0; f[root] = inf; getRoot(cur,-1,sum); int tmp_r = root; vis[tmp_r] = 1; //printf("====%d,%d\n",cur,tmp_r); for(int i = 0;i<(int)nod[tmp_r].size();i++){ int nxt = nod[tmp_r][i].nxt; if(vis[nxt]) continue; CDQ(nxt,size[nxt]); } int id = 0; top = 0; for(int i = 0;i<(int)nod[tmp_r].size();i++){ int nxt = nod[tmp_r][i].nxt; if(vis[nxt]) continue; int val = nod[tmp_r][i].val; dfs(nxt,tmp_r,val,min(wgt[nxt],wgt[tmp_r]),++id); } sort(stk+1,stk+top+1,Cmp); STK pri1 = STK(0,inf,0),pri2 = STK(-1,inf,0); for(int i = 1;i<=top;i++){ if(pri1.id!=stk[i].id) ans = max(ans,(LL)stk[i].wei*(stk[i].len + pri1.len)); else ans = max(ans,(LL)stk[i].wei*(stk[i].len + pri2.len)); if(pri1.len < stk[i].len){ if(pri1.id==stk[i].id) pri1 = stk[i]; else{ pri2 = pri1; pri1 = stk[i]; } } else if((pri2.len<stk[i].len)&&(stk[i].id!=pri1.id)){ pri2 = stk[i]; } } vis[tmp_r] = 0; } void init(){ for(int i = 0;i<N;i++) nod[i].clear(); memset(vis,0,sizeof(vis)); } int main(){ int T,a,b,n,v; //freopen("Test.txt","r",stdin); scanf("%d",&T); while(T--){ init(); scanf("%d",&n); for(int i = 1;i<=n;i++) scanf("%d",&wgt[i]); for(int i = 1;i<n;i++){ scanf("%d%d%d",&a,&b,&v); nod[a].push_back(Node(b,v)); nod[b].push_back(Node(a,v)); } ans = 0; CDQ(1,n); printf("%lld\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u012969412/article/details/47143843