0%

树的重心 P2986 [USACO10MAR] Great Cow Gathering G

思路讲解

https://www.bilibili.com/video/BV1SGsfeKExw/?vd_source=4350e5f2584d2f27c848b347ea11b675

image

树的重心是指以该点为根,其最大子树最小

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <vector>
#include <bitset>
#define ll long long
using namespace std;
const int maxn = static_cast<int>(1e5) + 7;
const long long MAXSON=1e18+7;
int n,a,b,l,core;
int c[maxn];
long long maxSonTree[maxn],minSon=MAXSON;
bitset</*100007*/ maxn> vis;
vector<pair<int,int> > g[maxn];
long long ans,sumN;
long long dfs(ll x,ll dis) {
long long accSon=0,maxSon=0,treeSon;
for(int i=0;i<g[x].size();i++) {
ll son=g[x][i].first,len=g[x][i].second;
if(!vis[son]) {
vis[son]=true;
treeSon=dfs(son,dis+len);
accSon+=treeSon;
maxSon=max(maxSon,treeSon);
}
}
// 这个节点过来的这颗子树我们没法直接统计,但可以用总的通过相减得到
maxSon = max(maxSon,sumN-accSon-c[x]); //accSon>sumN-accSon-c[x] ? accSon:sumN-accSon-c[x];
maxSonTree[x]=maxSon;
return accSon+c[x];
}

void dfs2(ll x,ll dis) { // 统计不方便值的
ans+=(c[x]*dis);
for(int i=0;i<g[x].size();i++) {
ll son=g[x][i].first,len=g[x][i].second;
if(!vis[son]) {
vis[son]=true;
dfs2(son,dis+len);
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) {
cin>>c[i];
sumN+=c[i];
}
for(int i=1;i<=n-1;i++) {
cin>>a>>b>>l;
// sumN+=l;
g[a].push_back(make_pair(b,l));
g[b].push_back(make_pair(a,l));
}
vis[1]=true;
dfs(1,0);
for(int i=1;i<=n;i++) {
if(maxSonTree[i]<minSon)
core=i,minSon=maxSonTree[i];
}
vis.reset(),ans=0;
vis[core]=true;
dfs2(core,0);
cout<<ans<<endl;
return 0;
}
// 30pts https://www.luogu.com.cn/record/178572159
// 40pts https://www.luogu.com.cn/record/178576100 删除了边权,但好像有点不对
// 遇到都read 0的情况大概率不是算法有问题,很有可能是某个min变量的初始值设小了
// 90pts https://www.luogu.com.cn/record/178578870 接近了

心路历程(WA,TLE,MLE……)