专栏文章
赛前模拟1-20250825(总结)
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mio51ook
- 此快照首次捕获于
- 2025/12/02 13:29 3 个月前
- 此快照最后确认于
- 2025/12/02 13:29 3 个月前
Part 1 赛时
T1
首先我们可以发现测试点分为两类:
- ,这只是一个普通的树,我们可以对每一个节点的子节点,按编号排序,进行贪心,时间复杂度,
- ,很明显,这是一个基环树,当时我已经想到了可以挨个断边,但当时我认为这太暴力了!,于是写了一个神奇的贪心,喜提
T2
看看这数据规模与约定:
| 测试点编号 | 分支不超过 | ||||
|---|---|---|---|---|---|
| 否 | 否 | 是 | |||
| 否 | 是 | 是 | |||
| 是 | 否 | 否 | |||
| 否 | 否 | 是 | |||
| 是 | 否 | 否 | |||
| 否 | 否 | 否 | |||
| 是 | 否 | 否 | |||
| 是 | 否 | 否 | |||
| 否 | 是 | 是 | |||
| 否 | 是 | 是 | |||
| 否 | 是 | 是 | |||
| 否 | 否 | 是 | |||
| 否 | 否 | 是 | |||
| 否 | 否 | 是 | |||
| 否 | 否 | 是 | |||
| 否 | 否 | 是 | |||
| 否 | 否 | 否 | |||
| 否 | 否 | 否 | |||
| 否 | 否 | 否 | |||
| 否 | 否 | 否 |
简单的数了一下,如果把所有特殊点加上,可以拿到,太值了,于是我完成了(3/4) -> 前三个,于是,我们来一个一个分析:
- m=1,这个十分明显,m=1代表只用出现一条赛道,如果要让这条赛道的长度最长,这条赛道其实就是这个树的直径,十分简单
- ai=1,这是一个菊花图:

对于这种情况,我们发现每一条赛道至多为2条边,如果,很明显我们直接曲最大的个,一大一小进行匹配,但是如果呢,我们可以加入若干条连接1的边,且其边为0,补全至第一种。
- ai=bi+1这是一条链,我们可以使用二分,每一次依次加边,直到>=mid,看能不能全部分配够。
T3
我在考场上,看到了这个:
| 测试点编号 | ||
|---|---|---|
A3 | ||
C3 | ||
A3 | ||
C3 | ||
A3 | ||
C3 | ||
A1 | ||
A2 | ||
A3 | ||
B1 | ||
C1 | ||
C2 | ||
C3 |
于是我先写了所有A的骗分,但时间复杂度算错了,只拿了
T4
暴力
Part 2 赛后
T1
赛后我很快发现暴力断边的时间复杂度 完全可以啊,于是就。
T2
肉眼可得: 我们可以使用二分答案,check的内容为长度大于等于mid是否能超过m个。
这道题我们可以发现每一个赛道可以分解为两条链,我们记录一下沿着每一个当前节点的子节点向下的最长链,为了满足要求,我们应当选择两条链使其最接近mid,如果剩下一些链没写,传上去。
(当然,如果一条链就大于mid了,便直接ans++)
这一段可以使用set实现,但我用的是数组。
CPPfor(int i=1;i<cnt;i++){
if(vis[i]) continue;
int it=lower_bound(a+i+1,a+cnt+1,mid-a[i])-a;
if(it==cnt+1) continue;
while(vis[it]&&it<cnt) it++;
if(!vis[it]&&a[i]+a[it]>=mid)
ans++,vis[i]=vis[it]=1;
}
code:
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
/*!@#$%^&*!@#$%^&*~~优美的分界线~~*&^%$#@!*&^%$#@!*/
const int N=5e4+5;
int n,m;
int ans,mid;
int a[N],b[N],vis[N];
int tot,head[N],ver[N<<1],nxt[N<<1],edg[N<<1];
/*!@#$%^&*!@#$%^&*~~优美的分界线~~*&^%$#@!*&^%$#@!*/
void add(int a,int b,int c){
ver[++tot]=b,edg[tot]=c;
nxt[tot]=head[a],head[a]=tot;
}
void dfs(int x,int fa){
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
if(y==fa) continue;
dfs(y,x);
}
int cnt=0;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i],w=edg[i];
if(y==fa) continue;
if(b[y]+w>=mid) ans++;
else a[++cnt]=b[y]+w;
}
sort(a+1,a+cnt+1);
for(int i=1;i<=cnt;i++)
vis[i]=0;
for(int i=1;i<cnt;i++){
if(vis[i]) continue;
int it=lower_bound(a+i+1,a+cnt+1,mid-a[i])-a;
if(it==cnt+1) continue;
while(vis[it]&&it<cnt) it++;
if(!vis[it]&&a[i]+a[it]>=mid)
ans++,vis[i]=vis[it]=1;
}
b[x]=0;
for(int i=1;i<=cnt;i++)
if(vis[i]==0)
b[x]=a[i];
}
bool check(int x){
ans=0;
dfs(1,0);
return ans>=m;
}
/*!@#$%^&*!@#$%^&*~~优美的分界线~~*&^%$#@!*&^%$#@!*/
signed main(){
cin>>n>>m;
for(int i=1;i<n;i++){
int a,b,l;cin>>a>>b>>l;
add(a,b,l),add(b,a,l);
}
int l=0,r=1e17;
while(l<r){
mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<'\n';
return 0;
}
by __H_J_M__
by huangjieming0703
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...