bzoj2870 最長道路tree 並查集+樹的直徑
阿新 • • 發佈:2018-11-05
Description
H城很大,有N個路口(從1到N編號),路口之間有N-1邊,使得任意兩個路口都能互相到達,這些道路的長度我們視作一樣。每個路口都有很多車輛來往,所以每個路口i都有一個擁擠程度v[i],我們認為從路口s走到路口t的痛苦程度為s到t的路徑上擁擠程度的最小值,乘上這條路徑上的路口個數所得的積。現在請你求出痛苦程度最大的一條路徑,你只需輸出這個痛苦程度。
簡化版描述:
給定一棵N個點的樹,求樹上一條鏈使得鏈的長度乘鏈上所有點中的最小權值所得的積最大。
其中鏈長度定義為鏈上點的個數。
100%的資料n<=50000
其中有20%的資料樹退化成一條鏈
所有資料點權<=65536
Hint:建議答案使用64位整型
Solution
表示並不會邊分治。。不會動態點分治。。
考慮暴力。我們把v從大到小插入樹上,每次合併連通塊的時候維護一下連通塊內的最長鏈,用最長鏈*當前權值更新答案
由最長鏈的某個結論可知我們這樣維護做是nlogn的
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const int N=100005;
struct edge {int x,y,next;} e[N*2];
struct data {int x,id;} d[N];
struct line {int x,y;} l[N];
int size[N],fa[N],dep[N],bl[N];
int ls[N],acs[N],edCnt;
bool vis[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>= '0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y) {
e[++edCnt]=(edge) {x,y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {y,x,ls[y]}; ls[y]=edCnt;
}
void dfs1(int now) {
size[now]=1;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==fa[now]) continue;
fa[e[i].y]=now; dep[e[i].y]=dep[now]+1;
dfs1(e[i].y); size[now]+=size[e[i].y];
}
}
void dfs2(int now,int up) {
bl[now]=up; int mx=0;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y!=fa[now]&&size[e[i].y]>size[mx]) mx=e[i].y;
}
if (!mx) return ;
dfs2(mx,up);
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y!=fa[now]&&e[i].y!=mx) dfs2(e[i].y,e[i].y);
}
}
int find(int x) {
return (!acs[x])?x:(acs[x]=find(acs[x]));
}
bool cmp(data a,data b) {
return a.x>b.x;
}
int get_lca(int x,int y) {
for (;bl[x]!=bl[y];) {
if (dep[bl[x]]<dep[bl[y]]) std:: swap(x,y);
x=fa[bl[x]];
}
return dep[x]<dep[y]?x:y;
}
int get_dis(int x,int y) {
int lca=get_lca(x,y);
return dep[x]+dep[y]-dep[lca]*2;
}
void merge(int x,int y) {
x=find(x),y=find(y);
if (x==y) return ;
acs[x]=y;
int x1=l[x].x,y1=l[x].y,x2=l[y].x,y2=l[y].y;
if (get_dis(x1,y1)>get_dis(l[y].x,l[y].y)) {
l[y]=(line) {x1,y1};
}
if (get_dis(x1,y2)>get_dis(l[y].x,l[y].y)) {
l[y]=(line) {x1,y2};
}
if (get_dis(x1,x2)>get_dis(l[y].x,l[y].y)) {
l[y]=(line) {x1,x2};
}
if (get_dis(x2,y1)>get_dis(l[y].x,l[y].y)) {
l[y]=(line) {x2,y1};
}
if (get_dis(y1,y2)>get_dis(l[y].x,l[y].y)) {
l[y]=(line) {y1,y2};
}
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n=read();
rep(i,1,n) {
d[i].x=read(),d[i].id=i;
l[i].x=l[i].y=i;
}
std:: sort(d+1,d+n+1,cmp);
rep(i,2,n) add_edge(read(),read());
dfs1(dep[1]=1); dfs2(1,1);
LL ans=0;
rep(i,1,n) {
for (int j=ls[d[i].id];j;j=e[j].next) {
if (vis[e[j].y]) merge(e[j].x,e[j].y);
}
vis[d[i].id]=true;
int x=find(d[i].id);
ans=std:: max(1LL*d[i].x*(1+get_dis(l[x].x,l[x].y)),ans);
}
printf("%lld\n", ans);
return 0;
}