题目描述

一个人有很多的影子,新的旧的,他们不断消失重来。学者的影子在他苍白色的精神图景里成为了$n$个黑色的点,他们伸长的触手交叉形成了一颗黑色的树。假使每个影子点拥有一个权值$d_i$,黑色的树边也有一个权值$w_i$,对于一条黑色树的路径,令路径上所有影子点权值$d_i$的最小值为${min}_d$,路径上所有树边权值$w_i$的总和为$sum_w$,则该条路径的总权值为${min}_d\times sum_w$。路径的起点和终点可以是黑色树中的任意影子点,且路径中不能出现重复的影子点。
现在学者需要知道这棵黑色树里所有路径总权值中的最大值为多少


输入格式

第一行输入一个整数$T$,表示数据组数
每组数据第一行一个正整数$n$,表示影子点总数
之后$n$个整数,表示每个影子点的权值
之后$n-1$行,每行三个整数$u,v,w$表示一条连接$u,v$且权值为$w$的树边。数据保证不会出现重边,且一定构成树结构


输出格式

一共$T$行,表示当前这组数据的答案


样例

样例输入:

1
3
1 2 3
1 2 1
1 3 2

样例输出:

3


数据范围与提示

样例解释:

总权值最大的路径是$2\rightarrow 1\rightarrow 3$,${min}_d$为$min(1,2,3)=1$,${sum}_w$为$sum(1,2)=3$,因此答案为$1\times 3=3$。

数据范围:

对于$100\%$的数据$1\leqslant T\leqslant 10,1\leqslant n\leqslant {10}^5,1\leqslant d_i\leqslant {10}^9,1\leqslant u,v\leqslant n,1\leqslant w_i\leqslant {10}^9$
其中$35\%$的数据$1\leqslant n\leqslant 100$
其中最多有$50\%$的数据保证${10}^4\leqslant n\leqslant {10}^5$


题解

再一次没有打正解,显然正解是点分治。

然而我用的是比较玄学的并查集。

首先,将所有的点权从大到小排序,于将当前点和与其相连的所有点依次合并到一个集合中。

并查集维护当前集合中的最长路径长度和对应的两个端点。

保证当前这个点是并查集中最大的点,这样它肯定对$min_d$没有贡献。

那么,合并两个集合后集合的最长路分为两种情况:

  $\alpha.$其中一个集合的最长路。

  $\beta.$两个集合的最长路的端点相互连接。

这里就需要用到$LCA$了。

每次合并并查集之后用当前点的权值乘以最长路的总长度来更新最优结果即可。即使这个点不在当前合并后的集合的最长路上也是没有问题的,因为如果这样的话,必然已经在之前得到了对应的结果,这次合并不会对最终结果产生影响。

时间复杂度:$\Theta(n\log n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to,w;}e[200001];
int head[100001],cnt;
int n;
int f[100001],lft[100001],rht[100001],rk[100001];
int fa[100001][21],depth[100001];
long long dis[100001],len[100001];
pair<int,int> d[100001];
long long ans;
void pre_work()
{
memset(len,0,sizeof(len));
memset(head,0,sizeof(head));
memset(depth,0,sizeof(depth));
ans=cnt=0;
for(int i=1;i<=n;i++)f[i]=lft[i]=rht[i]=i;
}
void add(int x,int y,int w)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
e[cnt].w=w;
head[x]=cnt;
}
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt)
{
if(depth[e[i].to])continue;
depth[e[i].to]=depth[x]+1;
fa[e[i].to][0]=x;
for(int j=1;j<=20;j++)
fa[e[i].to][j]=fa[fa[e[i].to][j-1]][j-1];
dis[e[i].to]=dis[x]+e[i].w;
dfs(e[i].to);
}
}
int LCA(int x,int y)
{
int minn=1<<30;
if(depth[x]>depth[y])swap(x,y);
for(int i=20;~i;i--)
if(depth[fa[y][i]]>=depth[x])
y=fa[y][i];
if(x==y)return x;
for(int i=20;~i;i--)
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
return fa[x][0];
}
long long get_dis(int x,int y){return dis[x]+dis[y]-(dis[LCA(x,y)]<<1);}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
pre_work();
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
d[i]=make_pair(x,i);
}
sort(d+1,d+n+1,greater<pair<int,int> >());
for(int i=1;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
depth[1]=1;
dfs(1);
for(int i=1;i<=n;i++)rk[d[i].second]=i;
for(int i=1;i<=n;i++)
{
for(int j=head[d[i].second];j;j=e[j].nxt)
{
int to=find(e[j].to);
if(rk[d[i].second]<rk[to])continue;
len[0]=len[d[i].second],lft[0]=lft[d[i].second],rht[0]=rht[d[i].second];
if(len[to]>len[0]){len[0]=len[to];lft[0]=lft[to];rht[0]=rht[to];}
if((dis[0]=get_dis(lft[d[i].second],lft[to]))>len[0]){len[0]=dis[0];lft[0]=lft[d[i].second];rht[0]=lft[to];}
if((dis[0]=get_dis(rht[d[i].second],rht[to]))>len[0]){len[0]=dis[0];lft[0]=rht[d[i].second];rht[0]=rht[to];}
if((dis[0]=get_dis(lft[d[i].second],rht[to]))>len[0]){len[0]=dis[0];lft[0]=lft[d[i].second];rht[0]=rht[to];}
if((dis[0]=get_dis(rht[d[i].second],lft[to]))>len[0]){len[0]=dis[0];lft[0]=rht[d[i].second];rht[0]=lft[to];}
f[to]=d[i].second;lft[d[i].second]=lft[0];rht[d[i].second]=rht[0];len[d[i].second]=len[0];
}
ans=max(ans,len[d[i].second]*d[i].first);
}
printf("%lld\n",ans);
}
return 0;
}

rp++

[CSP-S模拟测试]:影子(并查集+LCA)的更多相关文章

  1. hdu 2874 Connections between cities (并查集+LCA)

    Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  2. hdu6074[并查集+LCA+思维] 2017多校4

    看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块 ...

  3. [CSP-S模拟测试]:Dash Speed(线段树+并查集+LCA)

    题目描述 比特山是比特镇的飙车圣地.在比特山上一共有$n$个广场,编号依次为$1$到$n$,这些广场之间通过$n−1$条双向车道直接或间接地连接在一起,形成了一棵树的结构. 因为每条车道的修建时间以及 ...

  4. Gym 100814C Connecting Graph 并查集+LCA

    Description standard input/output Statements Alex is known to be very clever, but Walter does not be ...

  5. Network-POJ3694并查集+LCA

    Network Time Limit: 5000MS   Memory Limit: 65536K       Description A network administrator manages ...

  6. [并查集+LCA USACO18OPEN ] Disruption

    https://www.luogu.org/problemnew/show/P4374 一看这道题就是一个妙题,然后题解什么树链剖分...珂朵莉树... 还不如并查集来的实在!我们知道并查集本来就是路 ...

  7. Mobile Phone Network CodeForces - 1023F(并查集lca+修改环)

    题意: 就是有几个点,你掌控了几条路,你的商业对手也掌控了几条路,然后你想让游客都把你的所有路都走完,那么你就有钱了,但你又想挣的钱最多,真是的过分..哈哈 游客肯定要对比一下你的对手的路 看看那个便 ...

  8. HDU6074 Phone Call (并查集 LCA)

    Phone Call Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Tota ...

  9. 习题:过路费(kruskal+并查集+LCA)

    过路费  [问题描述]在某个遥远的国家里,有 n 个城市.编号为 1,2,3,…,n.这个国家的政府修 建了 m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市 T 需 要收取的过路费 ...

随机推荐

  1. 【CF1210D】Konrad and Company Evaluation(vector,图论)

    题意:有i个人,m对两两之间的关系,第i个人初始的薪水为i,有q次操作,第i次操作会把v[i]号的薪水提升成n+i 如果两个人之间存在关系,薪水高的会向薪水低的炫耀 定义u,v,w为一个三元组,当u向 ...

  2. router登录逻辑实现页面跳转

    main.js文件中router.beforeEach((to, from, next) => { NProgress.start() const token = localStorage.ge ...

  3. Rainbow的信号 CH3801

    题目链接 题意:求n个整数任意取一个区间,一起进行xor,and,或or的操作,求xor的期望值,and的期望值,or的期望值. 思路:区间取的左端点为l,右端点为r,当r==l时,选的概率为1/n/ ...

  4. python中冒泡 排序法练习题

    # 第四题:写出冒泡排序函数,可以排序任意类型的元素,可以逆序 # 1.实现冒泡排序算法 # 2.可以排序任意类型的元素 # 3.能够通过参数设置进行逆序,默认升序 def my_sort(lt,ke ...

  5. python中常用得字符串,列表函数汇总

    字符串函数: 1,replace函数,替换函数.s = s.replace(old,new),老得元素被新的元素替换.注意不能直接写s.replace(old,new).要写s=s.replace(o ...

  6. Transition 过渡/转场动画(一)

    UIViewController 的转场效果 当viewController通过push 或 present 进行转场时, 系统自带的动画是从右侧push进来一个新的viewControler (或从 ...

  7. upc组队赛15 Lattice's basics in digital electronics【模拟】

    Lattice's basics in digital electronics 题目链接 题目描述 LATTICE is learning Digital Electronic Technology. ...

  8. 将QTP运行时的错误截图上传到QC

    Class QCImageErrorCapture Sub Class_Terminate() 'Check if the current test has failed. If failed the ...

  9. ID和Phone高压缩比存储和查询

    ID和Phone高压缩比存储和查询的简单例子, 无多线程处理 运行环境JDK8+maven 0. 模块分割 1. 基本思路 源文件BCP每一行都转为一个全局的RowID,可以直接映射到FileName ...

  10. 34.Merge Intervals(合并序列)

    Level:   Medium 题目描述: Given a collection of intervals, merge all overlapping intervals. Example 1: I ...