2478. [HZOI 2016]简单的最近公共祖先

★☆   输入文件:easy_LCA.in   输出文件:easy_LCA.out   简单对比

时间限制:2 s   内存限制:128 MB

【题目描述】

给定一棵有n个节点的有根树,根节点为1,每个节点有一个权值wi,求

即求所有无序节点对的LCA的权值之和。

树的节点编号为1~n,LCA表示两节点的最近公共祖先,即在它们的所有公共祖先中离根节点最远的节点。

【输入格式】

第一行一个整数n,表示节点数。

第二行n个正整数,表示每个点的权值。

以下n-1行每行两个整数x,y,表示树上有一条边连接节点x和节点y。

【输出格式】

一个整数,表示答案。

【样例输入】

3
1 2 3
1 2
1 3

【样例输出】

9

【数据范围与约定】

对于30%的数据,n<=1000。

对于60%的数据,n<=100000。

对于100%的数据,1<=n<=1000000,0<wi<=1000000。

【来源】

HZOI 2016

裸地lca竟然只过3点:

#include<iostream>
#include<cstdio>

using namespace std;
const int N=1000010;

int head[N],deep[N],w[N],jump[N][25];
int now=1,n,root=1;
long long answer;
struct node{
	int u,v,nxt;
}E[N];

inline int read()
{
	int x=0;char c=getchar();
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
	return x;
}

inline void add(int u,int v)
{
	E[now].v=v;
	E[now].nxt=head[u];
	head[u]=now++;
}

void make_deep(int root)
{
	for(int i=head[root];~i;i=E[i].nxt)
		if(!deep[E[i].v])
			deep[E[i].v]=deep[root]+1,
			jump[E[i].v][0]=root,
			make_deep(E[i].v);
}

inline void make_jump()
{
	for(int i=1;i<=19;i++)
		for(int j=1;j<=n;j++)
			jump[j][i]=jump[jump[j][i-1]][i-1];
}

inline int lca(int x,int y)
{
	if(deep[x]<deep[y])
		swap(x,y);
	for(int i=19;i>=0;i--)
		if(deep[jump[x][i]]>=deep[y])
			x=jump[x][i];
	if(x==y)
		return x;
	for(int i=19;i>=0;i--)
		if(jump[x][i]!=jump[y][i])
			x=jump[x][i],
			y=jump[y][i];
	return jump[x][0];
}

int main()
{
	freopen("easy_LCA4.in","r",stdin);
	freopen("easy=_LCA.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++)
		head[i]=-1,w[i]=read();
	for(int i=1;i<n;i++)
	{
		int u=read(),v=read();
		add(u,v);
		add(v,u);
	}
	deep[root]=1;
	make_deep(root);
	make_jump();
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=i;j++)
			answer+=w[lca(i,j)];
	
	printf("%lld",answer);
	return 0;
}

  

#include<cstdio>
#include<cstring>

#define Cu fclose(stdin);fclose(stdout);return 0;
#define Begin freopen("easy_LCA.in","r",stdin);freopen("easy_LCA.out","w",stdout);chul();Cu;

using namespace std;
const int maxn=1000010;

int w[maxn],head[maxn],size[maxn],tim;
long long ans=0;
typedef long long ll;
int fath[maxn];

struct op{
	int to,next;
}r[maxn<<1];

void insert(int fr,int to)
{
	tim++;
	r[tim].to=to;
	r[tim].next=head[fr];
	head[fr]=tim;
}

void dfs(int rt)
{
	size[rt]=1;
	int x=0,y;
	for(int i=head[rt];i;i=r[i].next)
	{
		y=r[i].to;
		if(fath[rt]==y)continue;
			fath[y]=rt;
		dfs(y);
		ans+=(ll)size[rt]*size[y]*w[rt];
		size[rt]+=size[y];
	}
}

void chul()
{
	int n,s,t;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&w[i]);
		ans+=w[i];
	}
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&s,&t);
		insert(s,t);
		insert(t,s);
	}
	dfs(1);
	printf("%lld
",ans);
}


int main()
{
	Begin;
}

  

原文地址:https://www.cnblogs.com/lyqlyq/p/7198747.html