在一起 (树的贡献问题) (2022湘潭大学竞赛)
作者:互联网
题目大意: 看上面.
思路:
- 首先dfs一遍,得到各个节点的子数量和子贡献
- 然后在dfs一遍,得到各个节点的总贡献
- 如何更新: dfs下来,所以父亲的总贡献是得到的,然后VAL[A] = val[f] - val[a](这个节点) -sz[a]*w +val[a]+ (total sz - sz[a]) *w
- 最后这个是有多个测试数据一定要记得清零
- 不仅仅数组,和一些其他的变量要清零, vector也要清0,(建图)!!,这次就是因为这个一直没有发现哪里错了,最骚的是那个样例是错的!!
#include <bits/stdc++.h> using namespace std; #define M 200005 #define ri register int int n,m; int T; struct dian{ int val,to; }; vector <dian> p[M]; long long sz[M],val[M],vis[M]; int num[M]; void dfs1(int a) { vis[a]=1; sz[a]=num[a]; for(ri i=0;i<p[a].size();i++) { int b=p[a][i].to; if(vis[b]) continue; dfs1(b); sz[a]+=sz[b]; val[a]+=1ll*sz[b]*p[a][i].val+val[b]; } } long long ans1,ans2; long long arr=0; void dfs2(int a,int f,int w) { if(f==0) { ans1=1;ans2=val[1]; } else { long long tmp=val[a]; tmp+=val[f]-1ll*w*sz[a]-val[a]; tmp+=(arr-sz[a])*w; val[a]=tmp; if(val[a]<ans2) { ans2=val[a]; ans1=a; } else { if(val[a]==ans2&&a<ans1) { ans1=a; } } } vis[a]=1; for(ri i=0;i<p[a].size();i++) { int b=p[a][i].to; if(vis[b]) continue; dfs2(b,a,p[a][i].val); } } int main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>T; while(T--) { cin>>n;arr=0; for(ri i=1;i<=n;i++) cin>>num[i],arr+=num[i],p[i].clear(); for(ri i=1;i<n;i++) { int a,b,c; cin>>a>>b>>c; dian t; t.to=b;t.val=c; p[a].push_back(t); t.to=a; p[b].push_back(t); } for(ri i=1;i<=n;i++) { val[i]=0;vis[i]=0; } dfs1(1); for(ri i=1;i<=n;i++) vis[i]=0; dfs2(1,0,0); cout<<ans1<<" "<<ans2<<endl; } return 0; }View Code
标签:sz,竞赛,val,湘潭,int,dfs,num,2022,ri 来源: https://www.cnblogs.com/Lamboofhome/p/16440033.html