『Balancing Act 树的重心』
樹的重心
我們先來認識一下樹的重心。
樹的重心也叫樹的質心。找到一個點,其所有的子樹中最大的子樹節點數最少,那么這個點就是這棵樹的重心,刪去重心后,生成的多棵樹盡可能平衡。
根據樹的重心的定義,我們可以通過樹形DP來求解樹的重心。
設\(Max_i\)代表刪去i節點后樹中剩下子樹中節點最多的一個子樹的節點數。由于刪去節點i至少將原樹分為兩部分,所以滿足\(\ \frac{1}{2}n \leq Max_i\),我們要求的就是一個\(i\),使得\(Max_i\)最小。
對于Max數組,我們可以列出如下狀態轉移方程:
\[ Max_i=\max_{j\in son(i)}\{size_j,n-size_i\} \]
size數組即為節點個數(樹的大小),可以在樹形DP中順帶求解。
\(Code:\)
inline void dp(int r,int f) {size[r]=1;for(int i=0;i<Link[r].size();i++){int Son=Link[r][i];if(Son==f)continue;dp(Son,r);size[r]+=size[Son];Max[r]=max(Max[r],size[Son]);}Max[r]=max(Max[r],n-size[r]);if(Max[r]==Max[ans]&&r<ans)ans=r;if(Max[r]<Max[ans])ans=r; }還是通過一道例題來認識一下。
Balancing Act(POJ1655)
Description
The city consists of intersections and streets that connect them.
Heavy snow covered the city so the mayor Milan gave to the winter-service a list of streets that have to be cleaned of snow. These streets are chosen such that the number of streets is as small as possible but still every two intersections to be connected i.e. between every two intersections there will be exactly one path. The winter service consists of two snow plovers and two drivers, Mirko and Slavko, and their starting position is on one of the intersections.
The snow plover burns one liter of fuel per meter (even if it is driving through a street that has already been cleared of snow) and it has to clean all streets from the list in such order so the total fuel spent is minimal. When all the streets are cleared of snow, the snow plovers are parked on the last intersection they visited. Mirko and Slavko don’t have to finish their plowing on the same intersection.
Write a program that calculates the total amount of fuel that the snow plovers will spend.
Input Format
The first line of the input contains two integers: N and S, 1 <= N <= 100000, 1 <= S <= N. N is the total number of intersections; S is ordinal number of the snow plovers starting intersection. Intersections are marked with numbers 1...N.
Each of the next N-1 lines contains three integers: A, B and C, meaning that intersections A and B are directly connected by a street and that street's length is C meters, 1 <= C <= 1000.
Output Format
Write to the output the minimal amount of fuel needed to clean all streets.
Sample Input
5 2 1 2 1 2 3 2 3 4 2 4 5 1Sample Output
6解析
這個就是樹的重心的模板題了嘛。
還有題目的第二問就是重心子樹中節點數最多的子樹的節點數。嗯!剛好符合我們Max數組的定義,直接輸出就可以了。
\(Code:\)
#include<cstdio> #include<iostream> #include<queue> #include<vector> #include<cstring> #define mset(name,val) memset(name,val,sizeof name) using namespace std; const int N=20000+50; int n,size[N],Max[N],ans,cnt; vector < int > Link[N]; inline void input(void) {scanf("%d",&n);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);Link[x].push_back(y);Link[y].push_back(x);} } inline void dp(int r,int f) {size[r]=1;for(int i=0;i<Link[r].size();i++){int Son=Link[r][i];if(Son==f)continue;dp(Son,r);size[r]+=size[Son];Max[r]=max(Max[r],size[Son]);}Max[r]=max(Max[r],n-size[r]);if(Max[r]==Max[ans]&&r<ans)ans=r;if(Max[r]<Max[ans])ans=r; } int main(void) {int T;scanf("%d",&T);while(T--){mset(Max,0x00);mset(size,0x00);ans=0;cnt=0;Max[0]=0x3f3f3f3f;input();dp(1,0);printf("%d %d\n",ans,Max[ans]);for(int i=1;i<=n;i++)Link[i].clear();} }轉載于:https://www.cnblogs.com/Parsnip/p/10371480.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的『Balancing Act 树的重心』的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java面向对象中的抽象,类与对象
- 下一篇: UnicodeMath数学公式编码_翻译