神奇构造题,感觉自己想到了一丢丢,但是没有往正解的方向去想。
给出一张 个节点的树,从 中最多每个数选一次填到树中,求一种任意两个节点权值之差都不是质数的填数方案。
比赛的时候考虑到了 这个特殊条件,可以考虑只用偶数或者是奇数,假设是只用 的话,。
首先想到的是奇偶染色,然后分别把 和 填到不同颜色中。
然后发现这样全是不合法,所以把这种想法叉掉了。。。。
我们发现实际上就可以从这个角度来思考,先考虑给这个树分层,既然刚刚都顺着填的思路是很错误的,那我们反过来,用一个 Meet in
the middle 的思路来进行染色。
也就是根据 bfs 序和层数的奇偶性来进行填充,对于所有奇数层,我们把 按顺序填进去;对于 所有的偶数层,我们把 按照顺序填进去,这样一定最后填完的时候不会重,并且大体上都是合法的,因为所有的相邻差都是偶数,并且基本上都不是 。那么什么地方会是 呢?肯定就是我们最后meet的地方,而且它一定在叶节点,并且只有这一个不合法的地方,我们直接对他进行 就可以了。
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N=2e5+10; |
| int T,n; |
| inline void solve() |
| { |
| cin>>n; |
| vector<int> e[n+2],a(n+1,0),isf(n+1,0); |
| vector<vector<int>>num(2,vector<int>(n+2,0)); |
| for(int i=1;i<=n;++i)num[0][i]=i<<1,num[1][i]=(n-i+1)<<1; |
| for(int i=1,u,v;i<n;++i) |
| { |
| cin>>u>>v; |
| e[u].push_back(v); |
| e[v].push_back(u); |
| } |
| queue<pair<int,int>> q; |
| int cnt[2]={0,0}; |
| q.push({1,0}); |
| while(q.size()) |
| { |
| int x=q.front().first,type=q.front().second; |
| q.pop(); |
| a[x]=num[type][++cnt[type]]; |
| for(auto v:e[x]) |
| { |
| if(a[v])continue; |
| isf[x]=1; |
| q.push({v,type^1}); |
| } |
| } |
| for(int i=1;i<=n;++i) |
| { |
| if(isf[i])continue; |
| for(auto v:e[i]) |
| { |
| if(abs(a[i]-a[v])==2) |
| { |
| if(a[i]>a[v])a[i]--; |
| else a[i]++; |
| goto OUTPUT; |
| } |
| } |
| } |
| OUTPUT:; |
| for(int i=1;i<=n;++i)cout<<a[i]<<' '; |
| cout<<'\n'; |
| } |
| int main() |
| { |
| ios::sync_with_stdio(0); |
| cin.tie(0),cout.tie(0); |
| cin>>T; |
| while(T--) |
| { |
| solve(); |
| } |
| return 0; |
| } |
这种奇怪构造应该可乱搞性挺高的,根据starsilk的说法,好像可以特判菊花,然后还是只用偶数,找到一条长度为 的链,然后根据奇偶染色的原理也可以做。
不过我不太懂。
构造题可以先构造出一种大体合法的方案,然后对于不合法的细节进行微调。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!