题目2 : 偶树的切分
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
6 1 2 3 1 4 1 1 5 6 2
样例输出
-
1
描述
如果一棵树节点数目是偶数,那么就称这棵树是偶树。给定一棵N个节点的偶树(编号1~N),小Hi想知道他最多可以同时切断多少条边,使得剩下的森林中每一个联通分量都是一棵偶树。
例如如下的偶树:
1 / | | \ 2 3 4 5 | 6
可以切断1-2之间边使得剩下的每个联通分量都是偶树。
输入
第一行包含一个偶数N。
以下N-1行每行包含两个整数a和b,表示a和b之间有一条边。
对于30%的数据,1 ≤ N ≤ 20
对于100%的数据, 1 ≤ N ≤ 100000
输出
输出最多可以切断的边数。
因为切掉的部分为偶数个节点,剩下的一定也是偶数个节点。所以一直进行dfs就行。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6;
int d[MAX],n,v[MAX],ans;
vector<int>e[MAX];
void cla(int k)
{
v[k]=1;
d[k]=1;
for(int i=0;i<e[k].size();i++)
{
int nex=e[k][i];
if(v[nex])continue;
cla(nex);
d[k]+=d[nex];
}
}
void dfs(int k)
{
v[k]=1;
for(int i=0;i<e[k].size();i++)
{
int nex=e[k][i];
if(v[nex])continue;
if(d[nex]%2==0) //子树中节点数为偶数
{
ans++; //切断这条边
dfs(nex);//继续以nex为根节点,进行操作
}
else dfs(nex);//子树节点数为奇数
}
}
int main()
{
scanf("%d",&n);
memset(d,-1,sizeof d);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
memset(v,0,sizeof v);
cla(1); //预处理,d[i]表示以i为根节点的子树中的节点数
memset(v,0,sizeof v);
ans=0;
dfs(1);
cout<<ans<<endl;
return 0;
}