BZOJ 1827 洛谷 2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gather
2024-08-30 23:53:59
【题解】
很容易想到暴力做法,枚举每个点,然后对于每个点O(N)遍历整棵树计算答案。这样整个效率是O(N^2)的,显然不行。
我们考虑如果已知当前某个点的答案,如何快速计算它的儿子的答案。
显然选择它的儿子作为集合点,它的儿子的子树内的奶牛可以少走当前点到儿子节点的距离dis,不在它儿子的子树内的奶牛要多走dis. 那么我们维护每个节点的子树内的奶牛总数(即点权和),就可以快速进行计算了。效率O(N).
#include<cstdio>
#include<algorithm>
#define N 200010
#define rg register
#define LL long long
using namespace std;
int n,tot,last[N],v[N];
LL ans,sum,size[N],dis[N];
struct edge{
int to,pre,dis;
}e[N];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
void dfs(int x,int fa){
size[x]=v[x];
for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa){
dis[to]=dis[x]+e[i].dis;
dfs(to,x); size[x]+=size[to];
}
}
void solve(int x,int fa,LL now){
ans=min(ans,now);
for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa){
LL tmp=now-size[to]*e[i].dis+(sum-size[to])*e[i].dis;
solve(to,x,tmp);
}
}
int main(){
n=read();
for(rg int i=;i<=n;i++) v[i]=read(),sum+=v[i];
for(rg int i=;i<n;i++){
int u=read(),v=read(),w=read();
e[++tot]=(edge){v,last[u],w}; last[u]=tot;
e[++tot]=(edge){u,last[v],w}; last[v]=tot;
}
dfs(,);
for(rg int i=;i<=n;i++) ans+=dis[i]*v[i];
solve(,,ans);
printf("%lld\n",ans);
return ;
}
最新文章
- Unity相关路径
- Java后端书架
- Java Concurrency in Practice 读书笔记 第二章
- CentOS 修改线程数限制等(limits.conf)
- Application Loader上传app时报错:the bundle identifier cannot be changed from the current value
- C++ 中捕获整数除零错误
- linux xargs 使用
- SharePoint excel service web part 连接到 filter web part
- 深入浅出jsonp(转)
- Swing-布局管理器之GridLayout(网格布局)-入门
- TZOJ 4848 货车运输(最大生成树+倍增lca)
- sqlalchemy根据数据库结构生成映射的实体
- Python Django框架笔记(五):模型
- 一个web.Config或app.Config自定义段configSections的示例
- skill prefix neo,non input 1
- retinex相关代码汇总
- opencv学习笔记——图像缩放函数resize
- 三、angularjs上传图片
- 后台程序获取JPG/GIF/PNG图片宽度、高度
- centos-7 charpter one