题目
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
思路
思路
我们可以用样例来举例:
其中红色的每个连通线段是一条线段。
我们通过观察发现,每一个拥有子结点个数大于等于2的结点都必须要有子节点个数/2条线段来覆盖它与它的子结点们的这些边(例如上图中5的子结点个数有3个,3/2=1,需要1条线段来覆盖(6和4是一条,8已经被上面的以结点3开头的线段覆盖过了))。
代码
#include<bits/stdc++.h>
using namespace std;
int n,t;
vector<int> adj[100001];
void dfs(int u,int fa)
{
for(int i=0;i<adj[u].size();i++)
{
int k=adj[u][i];
if(k==fa)continue;
dfs(k,u);
}
t+=(adj[u].size()-(u!=1))/2; //如果当前结点不是根结点就要减去它的父结点的那一条边(因为根结点没有父结点)
}
int main()
{
cin>>n;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
adj[x].push_back(y); //双向建边
adj[y].push_back(x);
}
if(adj[1].size()==1) //特判根结点(如果只有一个儿子结点那也要用一条线段覆盖)
{
t++;
}
dfs(1,0);
cout<<t;
return 0;
}