话说去年为什么暴力炸成了15......
其实我现在都不会做,参考的一位P党大佬的题解,写成了C++版而已(附注了一些关键部分的细节)。
总之现在弄懂了QWQ
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10,maxm=2e6+10,inf=1e8;
int bg[maxn],nt[maxm],to[maxm],w[maxm],e;
int n,m,ed[maxn],num,st[maxn],top,cnt,up[maxn],ans;
void insert(int x,int y,int z) {
nt[++e]=bg[x];
to[e]=y;
w[e]=z;
bg[x]=e;
}
void dfs(int x,int fa,int lim) {
int i,j,u;
up[x]=0;
for (i=bg[x];i;i=nt[i]) {
u=to[i];
if (u==fa) continue;
dfs(u,x,lim);
}
num=0;
for (i=bg[x];i;i=nt[i]) {
u=to[i];
if (u==fa) continue; //PS:一顿苦调代码,结果好久才发现是这句话忘写了QAQ
ed[++num]=w[i]+up[u]; //每条边继承子节点的上传值
}
//贪心:
sort(ed+1,ed+num+1); //排完序使得边满足单调性
i=1; j=num; top=0;
while (ed[j]>=lim) { //假如大边可以自己(连带其子节点的上传值,之后省略这句话)成为一条赛道
j--;
cnt++;
}
while (i<=j) {
while (ed[i]+ed[j]>=lim && i<j) {
st[++top]=ed[j]; j--; //如果此时的较大边加上较小边满足条件,就将大边指针向左移,st内存的是囤积的大边(单调栈,top越大边权越小);
}
if (top) {top--; cnt++;} //如果有大边的存货就拿出一条与当前的小边匹配,因为此时小边一定大于之前的小边,所以一定能匹配上之前囤的大边中的最小值;
else up[x]=ed[i]; //没有存货说明此时的小边没有匹配,因此将其上传(若up之前有东西也一定只是一条小于此时边的小边)
i++;
}
cnt+=top/2; //如果还存在大边剩余,就两两配对
if (top%2) up[x]=st[1]; //配对完还剩一个,就将最大的大边上传(之后的大边两两配对去,反正可以配好)
}
int ok(int x) {
int i;
cnt=0;
dfs(1,0,x);
return cnt>=m;
}
int main() {
int i,x,y,z,l=inf,r=0,mid;
scanf("%d%d",&n,&m);
for (i=1;i<n;i++) {
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
insert(y,x,z);
r+=z;
l=min(l,z);
}
r/=m;
while (l<=r) {
mid=(l+r)/2;
if (ok(mid)) {
ans=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}