[BZOJ3376]geng4512膜你题1:快递配对

xiaoxiao2021-02-28  46

【问题描述】

azui大爷厌倦了每天在家颓废的生活,于是开始打工送快递。Jeremy同学不想让azui大爷太轻松,于是想让他送快递的路程尽可能的长。

一句话来说就是:

给出一棵n个点的树,将这n个点两两配对,求所有可行的方案中配对两点间的距离的总和最大为多少。

 

【输入格式】

一个数n(1<=n<=100,000,n保证为偶数)

接下来n-1行每行三个数x,y,z表示有一条长度为z的边连接x和y(0<=z<=1,000,000,000)

【输出格式】

      一个数表示答案。

【样例输入】

6

1 2 1

1 3 1

1 4 1

3 5 1

4 6 1

 

【样例输出】

7

 

【样例解释】

(1,2)(3,4)(5,6)分别配对

 

【数据范围】

对于20%的数据,n <= 14

对于另20%的数据,所给的树是一条链。

对于100%的数据,n <= 100000

#include<iostream> #include<cstdio> using namespace std; typedef long long LL; const int N=1e5+5; int n, fa[N], fir[N], ecnt; struct node{ int e, w, next; }edge[N<<1]; LL ans, pcnt[N]; void Getin( int &shu ) { char c; int f=1; shu=0; for( c=getchar(); c<'0' || c>'9'; c=getchar() ) if( c=='-' ) f=-1; for( ; c>='0' && c<='9'; c=getchar() ) shu=shu*10+c-'0'; shu*=f; } void Link( int s, int e, int w ) { edge[ ++ecnt ].e=e; edge[ecnt].w=w; edge[ecnt].next=fir[s]; fir[s]=ecnt; edge[ ++ecnt ].e=s; edge[ecnt].w=w; edge[ecnt].next=fir[e]; fir[e]=ecnt; } void Dfs( int s ) { pcnt[s]=1; for( int i=fir[s]; i; i=edge[i].next ) if( edge[i].e!=fa[s] ){ fa[ edge[i].e ]=s; Dfs( edge[i].e ); pcnt[s]+=pcnt[ edge[i].e ]; } } int main() { Getin(n); for( int i=1; i<n; i++ ) { int a, b, c; Getin(a); Getin(b); Getin(c); Link( a, b, c ); } Dfs(1); for( int s=1; s<=n; s++ ) for( int i=fir[s]; i; i=edge[i].next ) if( fa[ edge[i].e ]==s ) ans+=min( pcnt[ edge[i].e ], n-pcnt[ edge[i].e ] )*edge[i].w; printf( "%lld\n", ans ); return 0; } /* 一条边断开后图被分为s1, s2两部分 用边的权值乘上min(s1,s2)即是答案 */

转载请注明原文地址: https://www.6miu.com/read-77102.html

最新回复(0)