几乎把我送退役的一道题,留在这里做个纪念。
考场看出来是原题结果为了求稳强行花了一个小时写了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 }