2 条题解
-
0
显然可以用 dp 的思想来完成。
倾定以 为根。考虑一个节点的答案为 ,当往下走一步走到子结点上时,显然离所有以该子节点为根的子树内的所有节点都近了一步,而离其它节点都远了一步,所以令 为以 为根的子树中的所有节点的权值之和。那么下移到 之后的答案是 。预处理一下就能秒,建议降黄。
代码:
#include<bits/stdc++.h> using namespace std; long long dp[100005]; long long dep[100005]; long long val[100005]; long long sz[100005]; vector<int> g[100005]; void dfs(int rt,int fa){ dep[rt]=dep[fa]+1; for(auto v:g[rt]){ if(v!=fa){ dfs(v,rt); sz[rt]+=sz[v]; } } sz[rt]+=val[rt]; } void DFS(int rt,int fa){ if(rt>1){ dp[rt]=dp[fa]-sz[rt]+(sz[1]-sz[rt]); } for(auto v:g[rt]){ if(v!=fa){ DFS(v,rt); } } } int main(){ int n; cin>>n; for(int i=1;i<n;i++){ int x,y; cin>>x>>y; g[x].push_back(y); g[y].push_back(x); } for(int i=1;i<=n;i++){ cin>>val[i]; } dep[0]=-1; dfs(1,0); for(int i=1;i<=n;i++){ dp[1]+=1LL*val[i]*dep[i]; } DFS(1,0); long long ans=LONG_LONG_MAX; for(int i=1;i<=n;i++){ ans=min(ans,dp[i]); } cout<<ans; return 0; } -
0
重心应该都会找吧。
#include<bits/stdc++.h> using namespace std; #define int long long const int N=2e5+10; vector<int>G[N]; int a[N],sum[N],ans,n,sumn; void dfs1(int x,int f,int dep) { sum[x]=a[x];ans+=dep*a[x];sumn+=a[x]; for(int y:G[x])if(y!=f) { dfs1(y,x,dep+1); sum[x]+=sum[y]; } } void dfs2(int x,int f,int s) { ans=min(ans,s); for(int y:G[x])if(y!=f&&sum[y]>sumn/2) dfs2(y,x,s+sumn-sum[y]*2); } signed main() { cin>>n; for(int i=1;i<n;i++) { int x,y;cin>>x>>y; G[x].push_back(y); G[y].push_back(x); } for(int i=1;i<=n;i++)cin>>a[i]; dfs1(1,0,0);dfs2(1,0,ans); cout<<ans<<'\n'; return 0; }
- 1
信息
- ID
- 7720
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 3
- 上传者