唉,这题考场想到了,就是细节搞爆了。。。
主要是二分答案然后判一下,每次深搜(类似贪心)即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int v,fr,l;}e[100010];
int tail[50010],len[50010],a[50010],n,m,l=0,r=0,mid,ans=0,cnt=0,tot;
inline int read()
{
int x=0; char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') x=x*10+c-48,c=getchar();
return x;
}
void add(int u,int v,int l) {e[++cnt]=(node){v,tail[u],l}; tail[u]=cnt;}
int pd(int x,int l,int r)
{
int s=0;
while (l<r)
{
if (r==x) r--;
while (l<r && a[l]+a[r]<mid) l++;
if (l==x) l++;
if (l<r) s++,l++,r--;
}
return s;
}
void dg(int x,int fa)
{
for (int p=tail[x];p;p=e[p].fr)
if (e[p].v!=fa) dg(e[p].v,x);
int m=0;
for (int p=tail[x];p;p=e[p].fr)
if (e[p].v!=fa)
{
len[e[p].v]+=e[p].l;
if (len[e[p].v]>=mid) tot++;
else a[++m]=len[e[p].v];
}
if (m==0) return;
else if (m==1) {len[x]+=a[1]; return;}
sort(a+1,a+m+1);a[0]=0;
int le=0,ri=m,mi,s=0,ma=pd(0,1,m);
while (le<=ri)
{
mi=le+ri>>1;
if (pd(mi,1,m)==ma) s=mi,le=mi+1;
else ri=mi-1;
}
tot+=ma;len[x]+=a[s];
}
int main()
{
freopen("track.in","r",stdin);
freopen("track.out","w",stdout);
n=read(),m=read();
for (int i=1,a,b,ll;i<n;i++)
{
a=read(),b=read(),ll=read();
add(a,b,ll),add(b,a,ll);r+=ll;
}
while (l<=r)
{
mid=l+r>>1;
memset(len,0,sizeof(len));
tot=0;dg(1,0);
if (tot>=m) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}