Solution
由题意可知是一个树形结构。若要使两两之间边权最小,尽量不能选重边,也就是说尽可能在节点所在子树里寻找答案。
显然与叶子节点相连的边必须选。然后考虑其他边:
- 若一棵子树中的节点有偶数个,那么两两配对即可,不用添加新的边权。
- 若一棵子树有奇数个节点,那么根节点要和其他子树连边,所以还要加上根节点与其父节点之间的边的边权。
综上, 统计子树大小,偶数不用处理,奇数加边权即可。
数据范围较大,注意开 。
时间复杂度: 。
Code
#include <iostream> #include <cstdio> #include <cstring> #define ll long long using namespace std; const int maxn=1e4+10; struct edge{ ll t,v,w; }e[maxn<<1]; ll T,n,tot,ans,hd[maxn]; void add(ll x,ll y,ll z){ tot++; e[tot].t=hd[x]; e[tot].v=y; e[tot].w=z; hd[x]=tot; } ll Dfs(ll u,ll fa,ll x){ ll cnt=1; for(int i=hd[u];i!=0;i=e[i].t) if(e[i].v!=fa) cnt+=Dfs(e[i].v,u,e[i].w); if(cnt%2) ans+=x; return cnt; } int main(){ ios::sync_with_stdio(false); cin>>T; ll x,y,z; while(T--){ memset(hd,0,sizeof(hd)); ans=tot=0; cin>>n; for(int i=1;i<n;i++){ cin>>x>>y>>z; add(x,y,z); add(y,x,z); } Dfs(1,0,0); cout<<ans<<endl; } return 0; }