小琛和他的学校(dfs)
生活随笔
收集整理的這篇文章主要介紹了
小琛和他的学校(dfs)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
鏈接:https://ac.nowcoder.com/acm/contest/3566/B
來源:牛客網(wǎng)
時(shí)間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 131072K,其他語言262144K 64bit IO Format: %lld
題目描述
小琛是一所學(xué)校的校長。 他的學(xué)校有n個(gè)校區(qū)(編號(hào)1~n),被n-1條雙向道路連接,呈樹形結(jié)構(gòu)。 第i個(gè)校區(qū)共有Ai個(gè)學(xué)生。 第i天早上,所有的學(xué)生會(huì)沿最短路走到第i個(gè)校區(qū)參加活動(dòng),晚上再原路返回。 一個(gè)人通過第j條通道一次(即一人次),需要小琛支付wj的維護(hù)費(fèi)用。 小琛想知道第n天結(jié)束之后,對(duì)于每一條通道,他總共需要支付多少費(fèi)用。 對(duì)于100%的數(shù)據(jù),1≤ n ≤ 200,000,1≤ A[i]≤ 10,000,1≤ w[i] ≤ 10,000。 輸入描述: 第一行一個(gè)整數(shù)n,表示校區(qū)的數(shù)量。 接下來一行,n個(gè)整數(shù),表示A1~An。 第3到第n+1行,每行包含3個(gè)整數(shù)。第i行包含三個(gè)整數(shù)ui-2,vi-2,wi-2,表示第i-2條通道所連接的兩個(gè)校區(qū)的編號(hào),以及一人次通過這條通道的費(fèi)用。輸出描述:
共n-1行,每行一個(gè)整數(shù)。 第i行的整數(shù)表示小琛對(duì)于第i條通道所需支付的費(fèi)用。示例1
輸入 復(fù)制 4 2 1 2 3 1 3 1 1 2 3 4 1 2 輸出 復(fù)制 24 60 56思路:
記錄以每個(gè)節(jié)點(diǎn)為root的子樹的節(jié)點(diǎn)個(gè)數(shù)和子樹中人數(shù)。 比如: 總節(jié)點(diǎn)為n,總?cè)藬?shù)為sum, 有a --- b這條邊, a為根的子樹節(jié)點(diǎn)有siz[a]個(gè), 該子樹人數(shù)tot[a]個(gè)人, b為根的子樹節(jié)點(diǎn)有siz[b]個(gè), 該子樹人數(shù)tot[b]個(gè)人; 先算一趟每條邊走過的次數(shù): 從a --->b: tot[a] * (n - siz[a]) 從b--->a: (sum - tot[a]) * siz[a] 所以有:ans[id] = val*(siz[to]*(sum-tot[to]) + tot[to]*(n-siz[to])); 每天要來回,結(jié)果乘2即可AC代碼:
#include <bits/stdc++.h> using namespace std; const int N = 2e5+5; typedef long long LL; /* val:邊權(quán) id:輸入順序的邊編號(hào) nxt:鏈?zhǔn)角跋蛐谴鎴D中下一條邊的編號(hào) idx:鏈?zhǔn)角跋蛐谴鎴D編號(hào),這里我從0開始編號(hào) head[]:記錄鄰接表中最后一條邊的編號(hào) siz[i]:記錄以i為根的子樹節(jié)點(diǎn)個(gè)數(shù) tot[i]:記錄以i為根的子樹的人數(shù) ans[i]:求解結(jié)果 */ struct Edge {int from;int to;int val;int id;int nxt; } edge[N<<1]; int head[N],idx; int siz[N]; int n; LL tot[N],ans[N]; LL sum; void init() {memset(head,-1,sizeof(head));idx = 0; } inline void add_edge(int from,int to,int val,int id) {edge[idx].from = from;edge[idx].to = to;edge[idx].val = val;edge[idx].id = id;edge[idx].nxt = head[from];head[from] = idx++; } void dfs(int u,int fa) {siz[u] = 1;for(int i = head[u]; ~i; i = edge[i].nxt){int to = edge[i].to;int val = edge[i].val;int id = edge[i].id;if(to != fa){dfs(to,u);siz[u] += siz[to];tot[u] += tot[to];ans[id] = val*(siz[to]*(sum-tot[to]) + tot[to]*(n-siz[to]));}} } int main() {scanf("%d",&n);sum = 0;for(int i = 1; i <= n; i++){scanf("%lld",&tot[i]);sum += tot[i];}int x,y,w;init();for(int i = 1; i < n; i++){scanf("%d%d%d",&x,&y,&w);add_edge(x,y,w,i);add_edge(y,x,w,i);}dfs(1,0);for(int i = 1; i < n; i++){printf("%lld\n",ans[i]*2);}return 0; }總結(jié)
以上是生活随笔為你收集整理的小琛和他的学校(dfs)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 被3整除的子序列(简单dp)
- 下一篇: 小魂和他的数列(dp+树状数组优化)