CF1833G Ksyusha and Chinchilla 题解
题意简介
在一棵树上删去一些边,使得形成的几个连通块,都有且仅有 $3$ 个结点。
多个答案时仅需输出任意一个。
每个测试点有多组测试数据。
解法
思路
首先注意到每个连通块都有且仅有 $3$ 个结点,所以节点数 $n$ 必须是 $3$ 的倍数。可以先特判。
考虑有解时,我们可以从下往上进行断边操作,可用 dfs 实现。 具体见 算法流程。
算法流程
- 记 $siz_i$ 为当前节点的子树中未被切断为单独的连通快的节点个数(有点绕)。换句话说,不经过断开的边所能到达的子树中的节点的个数。如下图,红色边为应断开的边,
$i$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ | $8$ | $9$ |
---|---|---|---|---|---|---|---|---|---|
$siz_i$ | $3$ | $2$ | $3$ | $1$ | $3$ | $2$ | $1$ | $1$ | $1$ |
可以自行理解一下。
- 计算 $siz_i$:将各个调用的返回值累加。
- $siz_i$ 可分以下情况:(记 $pre$ 为 $i$ 的父亲。)
- 当 $siz_i=3$ 时,断开边 $(i,pre)$。同时返回 $0$ 表示没有未被切断的节点(都被切断了)。
- 当 $siz_i<3$ 时,还不够一个连通块的节点数量 $3$,所以返回 $siz_i$。
- 当 $siz_i>3$ 时,节点数量太多,输出 $\texttt{-1}$,结束。
- 返回到主函数后,若返回值为 $0$,则有解,输出解。否则输出 $\texttt{-1}$,结束。
代码
#include <iostream> #include <vector> using namespace std; struct edge { int v,id; }; vector<edge> del;//记录删除的边 vector<edge> e[200001];//边表 int dfs(int now,int pre) { int siz=1; edge tofa; for(edge to:e[now])//遍历所有连边 { if(to.v!=pre) { siz+=dfs(to.v,now);//累加返回值 } else { tofa=to;//标记与父亲连的边 } } if(siz==3)//判断siz { if(pre!=-1)//特判,如果是根节点(1号),它没有父亲,不能删除与父亲连的边,不然会出错 { del.push_back(tofa); } return 0; } else if(siz<3) { return siz; } else { // puts("-1");不能直接输出-1,因为不能退出程序,也无法直接回到main函数 return 0x3f3f3f3f;//让返回值极大,导致在主函数的特判中判定为无解 } return 114514;//没用的,只是为了让编译器不报错 } int main() { int t; scanf("%d",&t); while(t--) { del.clear();//清除上一次的记录 // fill(vtoid,vtoid+n+1,0); int n; scanf("%d",&n); int u,v; if(n%3) { puts("-1"); for(int i=1;i<n;i++) { scanf("%d %d",&u,&v); } continue; } for(int i=1;i<=n;i++) { e[i].clear(); } for(int i=1;i<n;i++) { scanf("%d %d",&u,&v); e[u].push_back({v,i}); e[v].push_back({u,i}); } if(!dfs(1,-1))//特判,如果返回值为0,则完美分配了所有节点。反之没有,就无解。 { printf("%d\n",del.size()); for(edge d:del) { printf("%d ",d.id); } puts(""); } else { puts("-1"); } } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程