解题:NOIP 2018 赛道修建

题面

几乎把我送退役的一道题,留在这里做个纪念。

考场看出来是原题结果为了求稳强行花了一个小时写了80pts暴力,然后挂了55pts(真·暴力写挂),结果今天花了不到半个小时连想带写一遍95pts(T一个菊花图的点),淦,想想就气,A了就HE rank3了(434->509)(算了反正你太菜了当时不敢写,再打马后炮也没用了

然后左转这道题(这甚至是个弱化版),做完了(懒得卡那一个点的常了,开O2了)

 1 // luogu-judger-enable-o2
 2 #include<set>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=50005,inf=1e9;
 8 int p[N],noww[2*N],goal[2*N],val[2*N],deg[N],dp[N][2];
 9 int n,m,l,r,mid,ans,t1,t2,t3,cnt;
10 multiset<int> mst;
11 multiset<int>::iterator it1,it2;
12 void link(int f,int t,int v)
13 {
14     noww[++cnt]=p[f],p[f]=cnt;
15     goal[cnt]=t,val[cnt]=v,deg[t]++;
16 }
17 void DFS(int nde,int fth)
18 {
19     if(deg[nde]==1&&nde!=1) return ;
20     for(int i=p[nde];i;i=noww[i])
21         if(goal[i]!=fth) 
22         {
23             DFS(goal[i],nde);
24             dp[nde][0]+=dp[goal[i]][0];
25         }
26     for(int i=p[nde];i;i=noww[i])
27         if(goal[i]!=fth) 
28             mst.insert(dp[goal[i]][1]+val[i]);
29     while(!mst.empty()&&(*mst.rbegin()>=mid))
30         dp[nde][0]++,mst.erase(--mst.end());
31     while(mst.size()>1)
32     {
33         it1=mst.begin(); 
34         int tmp=*it1; mst.erase(it1);
35         it2=mst.lower_bound(mid-tmp);
36         if(it2!=mst.end()) 
37             dp[nde][0]++,mst.erase(it2);
38         else dp[nde][1]=max(dp[nde][1],tmp);
39     }
40     if(mst.size()) dp[nde][1]=max(dp[nde][1],*mst.begin());
41     mst.clear();
42 }
43 bool check()
44 {
45     memset(dp,0,sizeof dp);
46     DFS(1,0); return dp[1][0]>=m;
47 }
48 int main()
49 {
50     scanf("%d%d",&n,&m);
51     for(int i=1;i<n;i++)
52     {
53         scanf("%d%d%d",&t1,&t2,&t3),r+=t3;
54         link(t1,t2,t3),link(t2,t1,t3);
55     }
56     while(l<=r)
57     {
58         mid=(l+r)/2;
59         if(check()) l=mid+1,ans=mid;
60         else r=mid-1; 
61     }
62     printf("%d",ans);
63     return 0;
64 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9991526.html