cogs 2478. [HZOI 2016]簡單的最近公共祖先
阿新 • • 發佈:2017-08-23
lld fault 兩節點 有根樹 cnblogs ont 給定 tar algo 【輸出格式】
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
思路:從數據範圍來看,去n^2枚舉i,j進行計算lca肯定不行,所以轉換思想找規律。
可以發現ans+=w[i]*孩子的數量+子樹1*子樹2+子樹1*子樹3+······
錯因:數組越界。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 3000000 using namespace std; int n,tot; long long ans; int w[MAXN],size[MAXN],dad[MAXN]; int to[MAXN],head[MAXN],net[MAXN]; void add(int u,int v){ to[++tot]=v;net[tot]=head[u];head[u]=tot; to[++tot]=u;net[tot]=head[v];head[v]=tot; }void dfs(int now){ size[now]=1; for(int i=head[now];i;i=net[i]) if(dad[now]!=to[i]){ dad[to[i]]=now; dfs(to[i]); ans+=1ll*size[now]*size[to[i]]*w[now]; size[now]+=size[to[i]]; } } int main(){ freopen("easy_LCA.in","r",stdin); freopen("easy_LCA.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&w[i]); ans+=w[i]; } for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); } dfs(1); printf("%lld",ans); }
cogs 2478. [HZOI 2016]簡單的最近公共祖先