首先二分一下答案,就变成了找长度>=m的 不相交的路径的个数
考虑到在一个子树中,只有一个点能出这个子树去和别的点搞
所以我这个子树里尽量自我满足是不会有坏处的
而且要在自我满足数最大的条件下,剩下一个尽量大的去把他搞出去
具体来说,我们设f[x]是x的子树中的满足条件的最大路径数,g[x]是在f[x]最大的情况下能剩下来的x的子树中到x的最大的路径长度
我们假设y们是x的孩子们,那我们拿着g[y]+edge[x][y],又可以拼出好多路径
首先如果他已经>=m了,那就直接f[x]++
然后我把剩下的排个序,开一个l一个r,对着扫,我找能满足它的最小的那个,然后把他俩踢掉
但踢完以后我还要把r往右搞,因为有可能再把它往左搞的话他就不能满足新的l+1了
所以需要用一个双向链表来做
但还有一个问题,我不能在l>=r的时候就直接跳出,考虑1 2 4 5,我第一次做完以后l指在4 r也指在4 所以我要让r再跳一跳,直到他跳出去了在结束
还是看代码吧...
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e4+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){ 11 if(c=='-') neg=-1; 12 c=getchar(); 13 } 14 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 15 return x*neg; 16 } 17 18 int eg[maxn*2][3],egh[maxn],ect; 19 int N,M,f[maxn],g[maxn],son[maxn],sh; 20 int nxt[maxn],pre[maxn]; 21 22 inline void adeg(int a,int b,int c){ 23 eg[++ect][0]=b,eg[ect][1]=c,eg[ect][2]=egh[a],egh[a]=ect; 24 } 25 26 inline bool cmp(int a,int b){ 27 return g[a]<g[b]; 28 } 29 30 void dfs(int x,int fa,int k){ 31 f[x]=g[x]=0; 32 for(int i=egh[x];i;i=eg[i][2]){ 33 int b=eg[i][0];if(b==fa) continue; 34 dfs(b,x,k); 35 }sh=0; 36 for(int i=egh[x];i;i=eg[i][2]){ 37 int b=eg[i][0];if(b==fa) continue; 38 son[++sh]=b; 39 g[b]+=eg[i][1];f[x]+=f[b]; 40 } 41 sort(son+1,son+sh+1,cmp); 42 int l=1,r=sh; 43 pre[0]=0;nxt[0]=1,pre[sh+1]=sh;nxt[sh+1]=0; 44 for(int i=1;i<=sh;i++){ 45 pre[i]=i-1;nxt[i]=i+1; 46 } 47 for(;r;r=pre[r]){ 48 if(g[son[r]]<k) break; 49 f[x]++; 50 pre[nxt[r]]=pre[r],nxt[pre[r]]=nxt[r]; 51 } 52 for(;l<=sh;l=nxt[l]){ 53 for(;l<pre[r]&&g[son[l]]+g[son[pre[r]]]>=k;r=pre[r]); 54 if(l<r&&r<=sh&&g[son[l]]+g[son[r]]>=k){ 55 f[x]++; 56 pre[nxt[r]]=pre[r],nxt[pre[r]]=nxt[r]; 57 pre[nxt[l]]=pre[l],nxt[pre[l]]=nxt[l]; 58 r=nxt[r]; 59 } 60 while(nxt[l]<=sh&&r<=nxt[l]) r=nxt[r]; 61 } 62 if(pre[sh+1]) g[x]=g[son[pre[sh+1]]]; 63 } 64 inline bool judge(int k){ 65 dfs(1,0,k); 66 return f[1]>=M; 67 } 68 69 int main(){ 70 // freopen("track.in","r",stdin); 71 // freopen("track.out","w",stdout); 72 int i,j,k; 73 N=rd(),M=rd(); 74 int l=0,r=0,ans=0; 75 for(i=1;i<N;i++){ 76 int a=rd(),b=rd(),c=rd(); 77 r+=c; 78 adeg(a,b,c);adeg(b,a,c); 79 } 80 while(l<=r){ 81 int m=l+r>>1; 82 if(judge(m)) l=m+1,ans=m; 83 else r=m-1; 84 } 85 printf("%d ",ans); 86 87 return 0; 88 }