二分一下答案长度
DP求直径
最长次长加起来爆了就把最长切了
明显提前切不优,没爆就不切
复杂度 (O(nlog^2n))
#include <cstdio>
#include <vector>
#include <functional>
#include <algorithm>
using std::sort;
using std::vector;
using std::greater;
const int MAXN=100111;
int N, K;
struct Vert{
int FE;
int Len;
} V[MAXN];
struct Edge{
int x, y, next;
} E[MAXN<<1];
int Ecnt;
void addE(int a, int b){
++Ecnt;
E[Ecnt].x=a;E[Ecnt].y=b;E[Ecnt].next=V[a].FE;V[a].FE=Ecnt;
}
int Lim, Kc;
void DFS(int at, int f=0){
vector<int> L;L.clear();
for(int k=V[at].FE, to;k>0;k=E[k].next){
to=E[k].y;
if(to==f) continue;
DFS(to, at);
L.push_back(V[to].Len+1);
}
L.push_back(0);L.push_back(0);
sort(L.begin(), L.end(), greater<int>());
for(unsigned int i=0U;(i+1U)<L.size();i+=1U){
if(L[i]+L[i+1U]>Lim)
++Kc;
else{
V[at].Len=L[i];
break;
}
}
}
bool Test(int l){
Lim=l;Kc=0;
DFS(1);
return (Kc<=K);
}
int main(){
scanf("%d%d", &N, &K);
for(int i=1, a, b;i<N;++i){
scanf("%d%d", &a, &b);
addE(a, b);addE(b, a);
}
int Left=0, Right=N, Mid;
while(Left<Right){
Mid=(Left+Right)>>1;
if(Test(Mid)) Right=Mid;
else Left=Mid+1;
}
Mid=(Left+Right)>>1;
printf("%d
", Mid);
return 0;
}
/*
7 2
6 7
3 4
6 5
1 2
3 2
4 5
2
*/