hihocoder1238(dfs)

xiaoxiao2021-02-28  71

链接:点击打开链接

题意:给定一颗有N个节点的带权树,之后进行M次操作:Q操作:询问树上所有点对之间的距离之和,E操作:修改树上某一条边的权值

代码:

#include <queue> #include <vector> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int siz=100005; struct node{ long long to,cost; }; vector<node> G[siz]; long long n,ans,dp[siz],dis[siz],val[siz]; void dfs(long long s,long long fa){ long long i,tmp; dp[s]=1; for(i=0;i<G[s].size();i++){ tmp=G[s][i].to; if(tmp==fa) continue; dis[tmp]=dis[s]+1; val[tmp]=G[s][i].cost; //把深度深的点设为边的编号 dfs(tmp,s); dp[s]+=dp[tmp]; ans+=(val[tmp]*(dp[tmp]*(n-dp[tmp]))); } } int main(){ //算每条边的贡献值,更新时直接根据 string s; //节点数更新 long long m,i,j,u,v,w; while(scanf("%lld%lld",&n,&m)!=EOF){ for(i=1;i<=n;i++) G[i].clear(); for(i=1;i<n;i++){ scanf("%lld%lld%lld",&u,&v,&w); G[u].push_back((node){v,w}); G[v].push_back((node){u,w}); } memset(dis,0,sizeof(dis)); memset(val,0,sizeof(val)); ans=0; dfs(1,0); while(m--){ cin>>s; if(s=="QUERY") printf("%lld\n",ans); else{ scanf("%lld%lld%lld",&u,&v,&w); if(dis[u]>dis[v]) swap(u,v); //直接根据子树点的个数更新 ans+=((w-val[v])*dp[v]*(n-dp[v])); val[v]=w; } } } return 0; }

转载请注明原文地址: https://www.6miu.com/read-33123.html

最新回复(0)