Cut 'em all! CodeForces - 982C(dfs)

本文探讨了一种针对树形结构的算法问题,即通过合理切割边的方式将树分割成多个节点数量为偶数的子树,以实现最大数量的边切割。文章详细介绍了算法的实现思路,并提供了一个具体的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C. Cut 'em all!
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You're given a tree with nn vertices.

Your task is to determine the maximum possible number of edges that can be removed in such a way that all the remaining connected components will have even size.

Input

The first line contains an integer nn (1n1051≤n≤105) denoting the size of the tree.

The next n1n−1 lines contain two integers uuvv (1u,vn1≤u,v≤n) each, describing the vertices connected by the ii-th edge.

It's guaranteed that the given edges form a tree.

Output

Output a single integer kk — the maximum number of edges that can be removed to leave all connected components with even size, or 1−1if it is impossible to remove edges in order to satisfy this property.

Examples
input
Copy
4
2 4
4 1
3 1
output
Copy
1
input
Copy
3
1 2
1 3
output
Copy
-1
input
Copy
10
7 1
8 4
8 10
4 7
6 5
9 3
3 5
2 10
2 5
output
Copy
4
input
Copy
2
1 2
output
Copy
0
Note

In the first example you can remove the edge between vertices 11 and 44. The graph after that will have two connected components with two vertices in each.

In the second example you can't remove edges in such a way that all components have even number of vertices, so the answer is 1−1


题意:有一颗树,现在,你需要切掉一些边,使这颗树分成若干个节点为偶数的部分,问,最多能切掉几条边。不能切,输出-1。

思路:首先,只有节点数为偶数的才能分成若干个偶数的部分,所以节点数为奇数的就直接输出-1吧。如果是偶数的话,从任意一点进行dfs,dfs返回的是子树节点的个数,如果是偶数的话,那么,父节点与子树的这条边一定是可以切掉的,所以,只要记录子树节点为偶数的个数就可以了。

#include "iostream"
#include "vector"
#include "cstdio"
using namespace std;
const int Max=1e5+10;
vector<int > G[Max];
bool flag[Max];//避免重复计算
int ans;
int dfs(int x)
{
    int res=0;
    for(int i=0;i<G[x].size();i++){
        int v=G[x][i];
        if(!flag[v]){
            flag[v]=1;
            int tmp=dfs(v);
            if(tmp%2==0) ans++;//如果子树节点的个数是偶数,那么,这条边就可以切掉
            res+=tmp;
        }
    }
    return res+1;//子树节点加一,就是这颗树的节点数
}
int main()
{
    int n,u,v;
    ans=0;
    scanf("%d",&n);
    for(int i=0;i<n-1;i++){
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    if(n%2!=0)//如果节点数为奇数,那么一定不可以切边
        printf("-1\n");
    else{
        flag[1]=1;
        dfs(1);
        printf("%d\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值