★☆ 输入文件: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\n",ans);
}
int main()
{
Begin;
}