专栏文章
题解:CF2040D Non Prime Tree
CF2040D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqtv9se
- 此快照首次捕获于
- 2025/12/04 10:39 3 个月前
- 此快照最后确认于
- 2025/12/04 10:39 3 个月前
CF992Div2 D-solution
给定一个 个节点的树,你可以不重复地给树的节点填 之间的数,求一种构造方案,使得每两个相邻的节点上的数之差的绝对值为合数。
我们规定每次填的数只会变大(就是在以某种方法遍历的时候后面的数一定比前面的数大)。现在我们假设填到了 节点, 节点填的数是 , 的儿子为 ,其中 是长儿子任意一个儿子。
现在我们归纳证明,如果每个 子树内最大的数小于 ,则存在一种构造方案,使得 子树内最大的数小于 。这样做下去根节点 的子树内最大的数小于 ,满足题意。
如果 ,即 没有儿子,显然满足条件。
我们填 ,下一个子树还能填的数是
-
如果 。显然 是一个合数,我们直接填 。则填完后还能从 填下一个子树,我们填 即可满足合数条件。执行这样的操作,我们可以保证填完所有子树后,还能填的数是 ,成立。
-
如果 。
-
如果 ,即 只有这一个子树,显然 。
-
否则填 ,那么接下来能填的数 ,于是我们填 即可满足合数条件。执行这样的操作,我们可以保证填完所有子树后,还能填的数是 ,成立。
-
于是就得证了。
所以只要一个 ,剩下的 的儿子找一个最小的 ,填 大于目前已填的数即可。
我写代码的时候是用长链填连续的数写的,稍微麻烦一点。主要还是证明要严格比较费脑子。
下面的代码是上面的做法。
CPP#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int>ttfa;
typedef long long ll;
const int N=200005;
int Test;
int n,tot=0,ans[N];
vector<int>tar[N];
void dfs(int u,int f){
bool flag=0;
ans[u]=++tot;
for(auto v:tar[u]){
if(v==f)continue;
if(!flag){
dfs(v,u);
flag=1;
continue;
}
if(tot+1-ans[u]==2)tot=ans[u]+3;
else if((tot+1-ans[u])%2==1)++tot;
dfs(v,u);
}
}
int main(){
scanf("%d",&Test);
while(Test--){
scanf("%d",&n);tot=0;
for(int i=1;i<=n;++i)
tar[i].clear();
for(int i=1;i<n;++i){
int u,v;scanf("%d%d",&u,&v);
tar[u].push_back(v);
tar[v].push_back(u);
}
dfs(1,0);
for(int i=1;i<=n;++i)
printf("%d ",ans[i]);
puts("");
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...