标签:数子 子树 求和 YBTOJ 路径 long int maxn 节点
题面:
题目分析:
考虑每一条边对于答案的贡献,根据树的性质,每一条边一定将整棵树分成了两个子树,而该边的贡献=子树1中叶节点数子树2中节点总数+子树2中叶节点数子树1中节点总数。
由于树有一个重要性质:
树的任意一个点都可以作为树的根
然后?没了。
哦不是,还有一个重要的点:
要注意乘法算式过程中的点要尽量多开long long,因为会爆int
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+100;
int head[maxn],ecnt=-1,m,a,b,c,du[maxn],root;
long long ans;
long long leaf[maxn],tot[maxn],n,totleaf;
struct mint
{
int nxt,v,w;
}e[maxn<<1];
inline void addline(int u,int v,int w)
{
e[++ecnt].nxt=head[u];
e[ecnt].v=v;
e[ecnt].w=w;
head[u]=ecnt;
}
void dfs(int now,int fa)
{
tot[now]=1;
if(du[now]==1)
{
totleaf++;
leaf[now]=1;
}
for(int i=head[now];~i;i=e[i].nxt)
{
int v=e[i].v;
if(v==fa) continue;
dfs(v,now);
leaf[now]+=leaf[v];
tot[now]+=tot[v];
}
return;
}
void find(int now,int fa)
{
for(int i=head[now];~i;i=e[i].nxt)
{
int v=e[i].v;
if(v==fa) continue;
find(v,now);
ans+=(long long)e[i].w*(leaf[v]*(n-tot[v])+tot[v]*(totleaf-leaf[v]));
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%lld%d",&n,&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&a,&b,&c);
du[c]++;
du[b]++;
addline(b,c,a);
addline(c,b,a);
}
dfs(1,0);
find(1,0);
printf("%lld",ans);
return 0;
}
标签:数子,子树,求和,YBTOJ,路径,long,int,maxn,节点 来源: https://www.cnblogs.com/mint-hexagram/p/15318539.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。