noip 2018 day1 T3 赛道修建 贪心 + 树上问题 + multiset
Code:
// luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; #define maxn 50008 #define MAXR 500000001 #define ll int multiset <ll> S[maxn]; multiset <ll> :: iterator it; int head[maxn], to[maxn << 1], nex[maxn << 1], val[maxn << 1]; int cnt,n, m, edges; ll mid; void setIO(string a){ freopen((a+".in").c_str(),"r",stdin); } void addedge(int u,int v,int c){ nex[++edges] = head[u], head[u] = edges, to[edges] = v, val[edges] = c; } void read(){ scanf("%d%d",&n,&m); for(int i = 1;i < n;++i){ int a,b,c; scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); } } ll dfs(int u,int fa){ S[u].clear(); for(int v = head[u]; v ; v = nex[v]){ if(to[v] == fa) continue; ll t = dfs(to[v], u) + val[v]; if(t >= mid) ++cnt; else S[u].insert(t); } ll MAX = 0; while(!S[u].empty()){ if(S[u].size() == 1) return max(MAX, *S[u].begin()); it = S[u].lower_bound(mid - *S[u].begin()); if(it == S[u].begin() && S[u].count(*it) == 1) it++; if(it == S[u].end()){ MAX = max(MAX, *S[u].begin()); S[u].erase(S[u].find(*S[u].begin())); } else { ++cnt ; S[u].erase(S[u].find(*it)); S[u].erase(S[u].find(*S[u].begin())); } } return MAX; } bool check(){ cnt = 0; dfs(1, 0); if(cnt >= m) return true; return false; } void solve(){ ll l = 0, r = MAXR, ans = 0; while(l <= r){ mid = (l + r) >> 1; if(check()) ans = mid, l = mid + 1; else r = mid - 1; } printf("%lld", ans); } void shut(){ fclose(stdin); } int main(){ //setIO("input"); read(); solve(); shut(); return 0; }