日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小琛和他的学校(dfs)

發布時間:2024/9/3 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小琛和他的学校(dfs) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈接:https://ac.nowcoder.com/acm/contest/3566/B

來源:牛客網


時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 131072K,其他語言262144K 64bit IO Format: %lld

題目描述

小琛是一所學校的校長。 他的學校有n個校區(編號1~n),被n-1條雙向道路連接,呈樹形結構。 第i個校區共有Ai個學生。 第i天早上,所有的學生會沿最短路走到第i個校區參加活動,晚上再原路返回。 一個人通過第j條通道一次(即一人次),需要小琛支付wj的維護費用。 小琛想知道第n天結束之后,對于每一條通道,他總共需要支付多少費用。 對于100%的數據,1≤ n ≤ 200,000,1≤ A[i]≤ 10,000,1≤ w[i] ≤ 10,000。 輸入描述: 第一行一個整數n,表示校區的數量。 接下來一行,n個整數,表示A1~An。 第3到第n+1行,每行包含3個整數。第i行包含三個整數ui-2,vi-2,wi-2,表示第i-2條通道所連接的兩個校區的編號,以及一人次通過這條通道的費用。

輸出描述:

共n-1行,每行一個整數。 第i行的整數表示小琛對于第i條通道所需支付的費用。

示例1

輸入 復制 4 2 1 2 3 1 3 1 1 2 3 4 1 2 輸出 復制 24 60 56

思路:

記錄以每個節點為root的子樹的節點個數和子樹中人數。 比如: 總節點為n,總人數為sum, 有a --- b這條邊, a為根的子樹節點有siz[a]個, 該子樹人數tot[a]個人, b為根的子樹節點有siz[b]個, 該子樹人數tot[b]個人; 先算一趟每條邊走過的次數: 從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])); 每天要來回,結果乘2即可

AC代碼:

#include <bits/stdc++.h> using namespace std; const int N = 2e5+5; typedef long long LL; /* val:邊權 id:輸入順序的邊編號 nxt:鏈式前向星存圖中下一條邊的編號 idx:鏈式前向星存圖編號,這里我從0開始編號 head[]:記錄鄰接表中最后一條邊的編號 siz[i]:記錄以i為根的子樹節點個數 tot[i]:記錄以i為根的子樹的人數 ans[i]:求解結果 */ 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; }

總結

以上是生活随笔為你收集整理的小琛和他的学校(dfs)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。