51nod 1737 配对 乱搞

来源:互联网 发布:sql 查询表的列名 编辑:程序博客网 时间:2024/05/18 22:11

题意

给出一棵n个点的树,将这n个点两两配对,求所有可行的方案中配对两点间的距离的总和最大为多少。(1<=n<=100,000,n保证为偶数)

分析

答案即为val[i]min(size[x],size[y])
val[i]表示第i条边的权值,size[x],size[y]表示这条边的两个端点对应的子树大小。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 100005#define ll long longusing namespace std;int n,cnt,last[N],x[N],y[N],z[N],size[N],dep[N];struct edge{int to,next;}e[N*2];void addedge(int u,int v){    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;    e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}void dfs(int x,int fa){    dep[x]=dep[fa]+1;size[x]=1;    for (int i=last[x];i;i=e[i].next)    {        if (e[i].to==fa) continue;        dfs(e[i].to,x);        size[x]+=size[e[i].to];    }}int main(){    scanf("%d",&n);    for (int i=1;i<n;i++)    {        scanf("%d%d%d",&x[i],&y[i],&z[i]);        addedge(x[i],y[i]);    }    dfs(1,0);    ll ans=0;    for (int i=1;i<n;i++)    {        int w;        if (dep[x[i]]<dep[y[i]]) w=y[i];        else w=x[i];        ans+=(ll)z[i]*min(size[w],n-size[w]);    }    printf("%lld",ans);    return 0;}
0 0
原创粉丝点击