偶数树 并查集
来源:互联网 发布:ubuntu root修改grub 编辑:程序博客网 时间:2024/06/06 05:25
Description
给你一棵有n个节点的树(一个无环简单图),节点序号为1~n,根节点为1。
请你找出一个最大的整数k,表示从这棵树上断掉k条边使其所有的子树的节点数都为偶数。
Input
第一行输入两个整数N,M。表示这棵树有N个节点和M条边。
接下来有M行,每行输入两个整数u,v,表示u节点和v节点间有一条边相连。
数据保证:2 ≤ n ≤ 100,并且所有的节点都在一棵树上。
输入的树总能被分解为包含偶数个节点的子树
Output
输出最多可以移除掉边的数量。
Sample Input
10 9
2 1
3 1
4 3
5 2
6 1
7 2
8 6
9 8
10 8
Sample Output
2
Hint
样例中移除掉(1,3)(1,6)两条边满足条件。
原始树:
分解的树:
题意
题解:
n为奇数的情况应该是不存在的 所以根节点1的子节点数一定是偶数(前提 记录初始值为1所以结果减一
思路也不是很难想 就是想要用并查集实现这点不容易 多想想应该可以写出来吧 (转化为有向图 序号统一由大指小)
把每个节点视为根节点 统计其子节点个数 那么要断掉的就是一个子节点个数(包括它自己)是否是偶数 如果是那么它和它的这一堆子节点便可以作为一个整体 然后便可以和它指向的点断开啦 经过这么操作 即可得到最多可以得出的数量啦(遍历了所有可能去断的节点) 又因为根节点 1 无指向节点而它的子节点个数(包括它自己)一定是偶数 所以结果要减 1
AC代码
#include <cstdio>#include <algorithm>using namespace std;int par[110],rkan[110];int n,m;void set_init(){ for (int i = 1; i <= n; ++i){ par[i] = i; rkan[i] = 1; }}int find(int x){ if (x == par[x]) return x; rkan[par[x]]++; return find(par[x]);}void set_unit(int x,int y){ int fx = find(x); int fy = find(y); if (fx!=fy){ if (x<y){ par[y] = x; rkan[x]++; }else { par[x] = y; rkan[y]++; } }}int main(){ scanf("%d%d",&n,&m); set_init(); int a,b; for (int i = 0; i < m; ++i){ scanf("%d%d",&a,&b); set_unit(a,b); } int ans = 0; for (int i = 1; i <= n; ++i){ if (rkan[i]%2==0){ ans++; } } printf("%d\n",ans-1); return 0;}
阅读全文
0 0
- 偶数树 并查集
- 树- 并查集
- 并查集判断树
- 10. 树--并查集
- 【bzoj4551】树 并查集
- HDU3938 并查集 并查集
- 并查集(集并查)
- HDU1232 并查集<并>
- POJ 2985 线段树+并查集
- Virtual Friends 字典树 并查集
- poj 2985 并查集 + 线段树
- pku1456贪心+并查集/线段树
- POJ 2513 Trie树+并查集
- poj 1308 并查集判断“树”
- hdu3172 字典树&&并查集
- 【并查集】判断是否为树
- hdu 3172 字典树+并查集
- hdu3172(字典树+并查集)
- 2.1面向对象程序设计基础(2)
- SVD分解
- Cent OS 7安装Tensorflow
- ProgressBar进度条
- JSTL格式化日期时报错:According to TLD or attribute directive in tag file, attribute value does not accept an
- 偶数树 并查集
- java中接口之间的继承
- hibernate笔记-006-双向的一对一映射
- Linux任务定时服务——crond与crontab
- static详解
- 一个支持memcache协议的支持在线批量更新的kv数据库(适用于推荐引擎)
- 从博客复制程序到VS里面出现<span style="font-size:24px;"><strong>
- 光流法
- 平方数