題目
題面bluesky007喜歡種樹。一天,她得到了一棵\(n\)個點的樹,其中節點\(i\)重量為\(w_i\) 。在種樹之前,bluesky007需要用起重機把樹吊起。由於她只有一台起重機,所以她只能選擇乙個點作為受力點。根據bluesky007所在世界的物理知識,吊起一棵樹需要做的功為\(\sum_^w_i\cdot dis_i\),其中\(dis_i\)表示節點\(i\)與受力點之間的距離(邊數)。
由於吊起這棵樹的費用與所做的功正相關,所以bluesky007希望所做的功盡可能小。請你幫助她求出吊起這棵樹所做的功的最小值。
題解本題是裸的換根dp,很好實現。設以1為根結點,dep[u]表示u到根的路徑長度,size[u]表示以u為根的子樹中所有結點的重量和,當以1為根結點時,dfs一遍求出總做功的值,即\(sum=\sum w[u]*dep[u]\)。接著考慮換根帶來的影響,當根從u換到兒子結點v時,v所在的子樹少做功size[v],v外的結點多做功size[1]-size[v],即\(sum'=sum-size[v]+(size[1]-size[v])=sum-2*size[v]+size[1]\)。
要使\(sum'\leq sum\),則\(sum-2*size[v]+size[1]\leq sum\),即\(size[1]\leq 2*size[v]\),所以在換根時,只有滿足\(2*size[v]\geq size[1]\)的兒子結點v才可能使得總做功值變小,可以利用這個條件進行剪枝。
**#includeusing namespace std;
const int n=2*1e5+5;
int n,w[n];
long long size[n],dep[n],sum,ans=1e18;
vectorg[n];
void dfs(int u,int fa)
}int main()
for(int i=1,u,v;i
2017種樹題解
每棵樹的費用為 cost i sum x i x k 由於 x i 與 x k 的大小關係的存在,我們可以把它分成兩部分 sum x i x k x i x k,1 le k le i 1 sum x k x i x i x k,1 le k le i 1 上面 1 式繼續展開 sum x i su...
洛谷1250 種樹
一條街的一邊有幾座房子。因為環保原因居民想要在路邊種些樹。路邊的地區被分割成塊,並被編號為1.n。每個塊大小為乙個單位尺寸並最多可種一棵樹。每個居民想在門前種些樹並指定了三個號碼b,e,t。這三個數表示該居民想在b和e之間最少種t棵樹。當然,b e,居民必須保證在指定地區不能種多於地區被分割成塊數的...
洛谷1484 種樹
cyrcyr今天在種樹,他在一條直線上挖了n個坑。這n個坑都可以種樹,但為了保證每一棵樹都有充足的養料,cyrcyr不會在相鄰的兩個坑中種 樹。而且由於cyrcyr的樹種不夠,他至多會種k棵樹。假設cyrcyr有某種神能力,能預知自己在某個坑種樹的獲利會是多少 可能為負 請你幫助他 計算出他的最大獲...