网站的按钮怎么做/自建站模板
链接:点击打开链接
题意:给定一颗有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;
}