bzoj2870 最长道路tree 并查集+树的直径

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/83351104

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;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/83351104
今日推荐