1 solutions
-
0
根据题目描述,很容易想到二分答案,当我们的道路越长,那么m就会越小,否则m就会更大,所以我们需要找到一个满足m的最长的道路
接下来如何去判断当前是否满足要求,我们可以从上往下搜索,对于每棵子树,我们优先去内部匹配,然后把没有匹配的最大值传到父亲节点,继续匹配。
#include<bits/stdc++.h> using namespace std; const int N=50010,INF=1e9; typedef pair<int,int> PII; #define x first #define y second int n,m; vector<PII> g[N]; int ans; int calc(vector<int> &q,int len,int k) { int res=0; for(int i=q.size()-1,j=0;i>=j;i--) { if(i==k) continue; if(q[i]>=len) { res++; } else { while(j<i&&(j==k||q[i]+q[j]<len)) j++; //q[j]太小了 if(j<i) //找到一组解 { res++; j++; } } } return res;//返回可以凑成的长度为len的段数 } int dfs(int u,int fa,int len) //递归搜索整个结构 { vector<int> q; for(auto t:g[u]) { if(t.x==fa) continue; q.push_back(dfs(t.first,u,len)+t.y); } if(q.empty()) return 0; sort(q.begin(),q.end());//排序 int mx=calc(q,len,-1);//计算不删除的最大组数 ans+=mx; int l=0,r=q.size()-1; while(l<r) { int mid=l+r+1>>1; if(calc(q,len,mid)==mx) l=mid; //说明当前l是可以删除的 else r=mid-1; } if(calc(q,len,r)!=mx) return 0;//说明删除了以后答案不准确了 return q[r];//可以删除r } bool check(int len) { ans=0; dfs(1,-1,len); return ans>=m; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<n;i++) //建图 { int a,b,c; scanf("%d%d%d",&a,&b,&c); g[a].push_back({b,c}); g[b].push_back({a,c}); } int l=0,r=INF; while(l<r) //二分查找最大值 { int mid=l+r+1>>1; if(check(mid)) l=mid; else r=mid-1; } printf("%d",r); return 0; }
- 1
Information
- ID
- 1132
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 8
- Tags
- # Submissions
- 1
- Accepted
- 1
- Uploaded By