保证k为偶数

 

 

题解

好题

性质题

这道题的理解关键就是P_{(i%k)+1},不是P_{i%(k+1)},也不是P_{i%k}+1

意思就是选一个点集P,依次走P_1,P_2……最后回到P_1的最大路径权值和

怎么办?

有一个关键的条件:k是偶数

我们考虑一下这个点集在树上的重心

如果我们想让得到的答案最大,我们一定会让这个集合反复横跳进过重心

然后发现,当路径重心的经过次数最大时,答案最大,且答案为点集中所有点到重心距离的两倍(画图感受一下。。。)

(注意一个点集在树上可能有多个重心,但是它们的答案算出来是一样的)

(有没有可能无法完成所有路径都经过重心的情况?没有,我们可以利用反证法,如果存在的话,当且仅当有从一个儿子上来的点的个数大于k/2,这与重心的定义不符)

于是我们可以二分答案?猜测重心的位置?

应该是点分治答案

首先猜全图的重心u

找到k个离u最远的点

如果有一个u的儿子pos的点的个数大于了k/2,我们就为了平衡,就会把下一个猜测的答案设为pos所在点分治区域的重心

(实际上就是在点分树上贪心)

如果当前点符合了条件,或者已经到了最小的分治区域,那么直接计算输出答案

 

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 200005
#define LL long long 
int n,k;
int fir[N],to[2*N],nxt[2*N],cd[2*N],cnt;
int siz[N],con[N],from[N];LL dis[N];
int all,mi,nrt;bool vis[N];
void adde(int a,int b,int c)
{
	to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;cd[cnt]=c;
	to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;cd[cnt]=c;
}
void find(int u,int ff)
{
	int mx=0;siz[u]=1;
	for(int v,p=fir[u];p;p=nxt[p]){
		v=to[p];
		if(v!=ff&&!vis[v]){
			find(v,u);
			siz[u]+=siz[v];
			mx=max(mx,siz[v]);
		}
	}
	mx=max(all-siz[u],mx);
	if(mx<mi)mi=mx,nrt=u;
}
int getrt(int u,int sz){mi=0x3f3f3f3f;nrt=0;all=sz;find(u,0);return nrt;}

void dfs(int u,int ff,int pre)
{
	from[u]=pre;
	for(int v,p=fir[u];p;p=nxt[p]){
		v=to[p];
		if(v!=ff){
			dis[v]=dis[u]+cd[p];
			dfs(v,u,!pre?v:pre);
		}
	}
}
int id[N];
bool cmp(int x,int y){return dis[x]>dis[y];}
void solve(int u)
{
	vis[u]=1;
	dis[u]=0;dfs(u,0,0);
	nth_element(id+1,id+k,id+n+1,cmp);
	memset(con,0,sizeof(con));
	int pos=0;
	for(int i=1;i<=k;i++){
		int ff=from[id[i]];
		if(con[ff]==k/2){pos=ff;break;}
		con[ff]++;
	}
	if(pos&&!vis[pos]){solve(getrt(pos,siz[pos]));}
	else{
		sort(id+1,id+n+1,cmp);
		memset(con,0,sizeof(con));
		LL ans=0;int ct=0;
		for(int i=1;i<=n;i++){
			int ff=from[id[i]];
			if(con[ff]==k/2)continue;
			con[ff]++;ans+=dis[id[i]];
			if((++ct)==k)break;
		}
		printf("%lld\n",2ll*ans);
	}
}
int main()
{
	int i,u,v,w;
	scanf("%d%d",&n,&k);
	for(i=1;i<n;i++){
		scanf("%d%d%d",&u,&v,&w);
		adde(u,v,w);id[i]=i;
	}
	id[n]=n;
	solve(1);
}