题目描述
给你一棵有n个节点的树(一个无环简单图),节点序号为1~n,根节点为1。
请你找出一个最大的整数k,表示从这棵树上断掉k条边使其所有的子树的节点数都为偶数。
输入
第一行输入两个整数N,M。表示这棵树有N个节点和M条边。
接下来有M行,每行输入两个整数u,v,表示u节点和v节点间有一条边相连。
数据保证:2 ≤ n ≤ 100,并且所有的节点都在一棵树上。
输入的树总能被分解为包含偶数个节点的子树。
输出
输出最多可以移除掉边的数量。
Input
Output
2
Hint
样例中移除掉(1,3)(1,6)两条边满足条件。
原始树:
分解的树:
请你找出一个最大的整数k,表示从这棵树上断掉k条边使其所有的子树的节点数都为偶数。
接下来有M行,每行输入两个整数u,v,表示u节点和v节点间有一条边相连。
数据保证:2 ≤ n ≤ 100,并且所有的节点都在一棵树上。
输入的树总能被分解为包含偶数个节点的子树。
10 9 2 1 3 1 4 3 5 2 6 1 7 2 8 6 9 8 10 8
原始树:
分解的树:
思路:不带路径压缩的带权并查集,ran统计每个点的子节点(题目中说没有环),最后记录ran为偶数节点的就可以断开,当然根节点1不能断(ans-1);
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define max_n 110
typedef long long LL;
using namespace std;
int pre[max_n],ran[max_n];
int find(int x)
{
if(pre[x]==x) return x;
ran[pre[x]]++;
return find(pre[x]);
}
int main()
{
int n,m,p1,p2,ans=0;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
ran[i]=1;
pre[i]=i;
}
for(int i=0;i<m;i++)
{
scanf("%d %d",&p1,&p2);
int fx=find(p1);
int fy=find(p2);
if(fx!=fy)
{
if(p1<p2)
{
pre[p2]=p1;
ran[p1]++;
}
else
{
pre[p1]=p2;
ran[p2]++;
}
}
}
for(int i=1;i<=n;i++)
{
if(ran[i]%2==0)
ans++;
// printf("%d\n",ran[i]);
}
printf("%d\n",ans-1);
return 0;
}