★☆ 输入文件: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; }