码迷,mamicode.com
首页 > 其他好文 > 详细

cf1280C——树的性质

时间:2019-12-27 18:18:04      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:F12   names   get   就是   span   统计   ems   name   div   

/*
给定一颗2n结点的树,求两个值:
    1.给每两个点配对,并且两点之间距离和最小
        从叶子结点往上统计,如果子树大小是偶数,那么其到父亲的边权就不用统计,反之要统计 
    2.给每两个点配对,并且两点之间距离和最大 
        每条边都被尽可能的访问,一条边将树分成两部分,取小的那部分的size*边权就是这条边的贡献 
*/
#include<bits/stdc++.h>
#include<vector> 
using namespace std;
#define N 300005
#define ll long long

ll n;
struct Edge{ll to,nxt,w;}e[N<<1];
ll head[N],tot;

void add(ll u,ll v,ll w){
    e[tot].to=v;e[tot].w=w;e[tot].nxt=head[u];head[u]=tot++;
}

ll size[N],val[N];
void getsize(int u,int fa){
    size[u]=1;
    for(int i=head[u];i!=-1;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa)continue;
        val[v]=e[i].w;
        getsize(v,u);
        size[u]+=size[v];
    } 
}
ll ans1,ans2;
void dfs1(int u,int fa){
    if(size[u]%2)ans1+=val[u];
    for(int i=head[u];i!=-1;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa)continue;
        dfs1(v,u);
    }
}
void dfs2(int u,int fa){
    ll tmp=min(size[u],n-size[u]);
    ans2+=tmp*val[u];
    
    for(int i=head[u];i!=-1;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa)continue;
        dfs2(v,u);
    }
    
}

void init(){
    memset(head,-1,sizeof head);
    tot=0;
    ans1=ans2=0;
}
int main(){
    int t;cin>>t;
    while(t--){
        init();
        scanf("%d",&n);n<<=1;
        for(int i=1;i<=n-1;i++){
            ll u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        
        getsize(1,1);
        dfs1(1,1);
        dfs2(1,1);
        
        cout<<ans1<<" "<<ans2<<\n;    
    }
}
 

cf1280C——树的性质

标签:F12   names   get   就是   span   统计   ems   name   div   

原文地址:https://www.cnblogs.com/zsben991126/p/12108688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!