【CF1917F】Construct Tree

1|0题目


题目链接:https://codeforces.com/contest/1917/problem/F
给出 n 条边的边权,询问是否可以构造出一棵树,使得所有边都被用上恰好一次且直径为 d
n,d2000

2|0思路


首先肯定是找出一条长度为 d 的链,然后判断可不可以把剩下的所有边都挂在这条链的带权重心上。
如果最长的两条边的和已经超过 d 了,那么无解。
否则,考虑最长的边是否在这个长度为 d 的链上:

  • 如果在,那就把最长的边放在链的最前端,然后将剩余的边都挂在链的第二个节点上。显然这样不会产生长度超过 d 的链。
  • 如果不在,那么需要找到这条链上是否存在一个点,使得这个点切开后两条新的链长度都不小于最长的边的长度。
    f[i][j][k] 表示是否存在一种情况,满足前 i 个边选择了若干个,使得第一条链长度为 j,第二条链长度为 k。然后直接上 01 背包即可。压掉第一维然后用 bitset 可以优化到 O(nd264)

时间复杂度 O(nd264)

3|0代码


#include <bits/stdc++.h> using namespace std; const int N=2010; int T,n,d,a[N]; int main() { scanf("%d",&T); while (T--) { scanf("%d%d",&n,&d); for (int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); if (a[n]+a[n-1]>d) { printf("No\n"); continue; } bitset<N> f[d+1]; f[0][0]=1; for (int i=1;i<n;i++) for (int j=d;j>=0;j--) { f[j]|=(f[j]<<a[i]); if (j>=a[i]) f[j]|=f[j-a[i]]; } bool flag=f[d-a[n]][0]; for (int i=a[n];i<=d-a[n];i++) flag|=f[i][d-i]; printf("%s\n",(flag ? "Yes" : "No")); } return 0; }

__EOF__

本文作者stoorz
本文链接https://www.cnblogs.com/stoorz/p/17932460.html
关于博主:菜死了 /fad
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   stoorz  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2020-12-28 【洛谷P6329】【模板】点分树 | 震波
2019-12-28 【JZOJ3800】败屩妖
2019-12-28 【JZOJ3799】青蛙神
2019-12-28 【JZOJ3798】临洮巨人
点击右上角即可分享
微信分享提示