Track construction (tree greedy + multiset)

P5021 track construction

analysis:

It is clear to a half value.

For the relationship between a track and a point u can be divided into three cases:

1. entirely within a subtree u. 2. subtree in half, the outer half of the subtree 3. After u, the other strand is connected to the subtree

In the first case, directly in the recursion when he included contributions.

For the second three cases, open a multiset, encountered no legal value is placed in the multiset.

Back each time, the first sub-tree can twenty-two combined merged, and not twenty-two combined, takes a maximum left to match its parent node.

multiset There are a lot of details:

1. erase can either delete a value, you can also delete a location! !

2. Delete the order is important, do not delete after a point, and that point to point, point to empty this time, resulting in a crash.

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define N 50005
int head[N],nex[N<<1],to[N<<1],tot=0,w[N<<1],n,m,mid,ans;
void add(int a,int b,int ww) {  tot++; to[tot]=b; nex[tot]=head[a]; head[a]=tot; w[tot]=ww; }
multiset<int> st[N];
multiset<int>::iterator it;//!!!在外面定义才能遍历完 
int dfs(int u,int ff)
{
    st[u].clear();
    int val;
    for(ri i=head[u];i;i=nex[i]){
        int v=to[i];
        if(v==ff) continue;
        val=dfs(v,u)+w[i];
        if(val>=mid) ans++;//子树内的链直接满足情况,就ans++ 
        else st[u].insert(val);
    }
    int mx=0;
    while(!st[u].empty()){
        if(st[u].size()==1) return mx=max(mx,*st[u].begin());
        ITST = [U] .lower_bound (mid- ST * [U] .begin ()); // find the position corresponding 
        IF (ST [U] .begin () && == IT ST [U] .count (IT * ) == . 1 ) iT ++; // if found themselves skipped
         // if the value does not exist the corresponding paired with it, that it is too small, to delete this value 
        IF (ST iT == [U]. End ()) = max MX (MX, ST * [U] .begin ()), ST [U] .erase (ST * [U] .begin ()); // Note that the value of the delete! ! 
        the else { // otherwise will be paired with a corresponding position 
            ANS ++ ;
             // NOTE sequence: first to delete it, or after deleting begin, if it points to begin, then it will point to an empty, will explode 
            st [u] .erase ( IT); 
            ST [U] .erase (ST [U] .begin ()); // this is the head position of the deletion, and should not be a value, because there are multiple values, the position of only one 
        } 
    } 
    return mx;
}
int main()
{
    scanf("%d%d",&n,&m);
    int sum=0,a,b,ww;
    for(ri i=1;i<=n-1;++i) scanf("%d%d%d",&a,&b,&ww),add(a,b,ww),add(b,a,ww),sum+=ww;
    int l=0,r=sum+1,anss=0;
    while(l<r){
        mid=(l+r)>>1; ans=0;
        dfs(1,0);
        if(ans<m) r=mid;
        else l=mid+1,anss=mid;
    }
    printf("%d\n",anss);
}
View Code

 

 

Guess you like

Origin www.cnblogs.com/mowanying/p/11838324.html