题目
Description
给你一棵树,问你,对于树上的所有边,你至少用多少条线段覆盖住它们
这些线段不能围成一个环,可以在点上相交,但不能有重合边。
规定树的根为1
Format
Input
第一行给出数字N
接下来N-1行,描述这个树
N<=1e5
Output
如题
Samples
输入数据 1
9
7 8
4 5
5 6
1 2
3 2
9 8
2 5
5 8
输出数据 1
4
思路
我们可以用样例来举例:
上图要用四条线段来覆盖:
我们应该这么做:dfs时判断当前遍历的节点是否为根并遍历它所有的子节点同时统计它的子节点个数s,后面在判断如果当前遍历的节点为根则ans += s / 2,否则ans += (s + 1) / 2即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,maxn,maxk,u,v,ans;
/*
pre[j]:对于第i条边来说,它的上一条边是哪一条边
now[x]:对于点x来说,最后一条描述它充当父结点的边是哪一条边
son[i]:在第i条边中,充当子结点的点是哪一个
*/
int eg,pre[100001],now[100001],son[100001];
void adeg(int u,int v)
{
pre[++eg] = now[u];
now[u] = eg;
son[eg] = v;
}
void dfs(int beg,int fa)
{
bool fl = 1;
int s = 0;
if(beg == 1) fl = 0;
for(int i = now[beg]; i; i = pre[i])
{
int v = son[i];
if(v == fa) continue;
dfs(v,beg);
s++;
}
if(fl == 1) ans += s / 2;
else ans += (s + 1) / 2;
}
signed main()
{
cin>>n;
for(int i = 1;i < n;i++)
{
cin>>u>>v;
adeg(u,v);
adeg(v,u);
}
dfs(1,0);
cout<<ans;
return 0;
}