/**
[树形DP] poj 3659 Cell Phone Network
给定一棵树,求最小支配集
dp[i][0] = sum(min(dp[s][2],dp[s][1]))自己没被选,父节点被选中
dp[i][1] = sum(min(dp[s][1],dp[s][2]))自己没被选,某儿子结点被选中
dp[i][2] = sum(min(dp[s][0],dp[s][1],dp[s][2]))自己被选中
求dp[i][1] 时需注意当所有的dp[s][1] < dp[s][2]时是不满足条件的。
*/
//纪念版的树形Dp
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define maxn 20000
#define inf 0x3f3f3f
#define INF 0x3f3f3f
using namespace std;
int dp[maxn][3];
vector<int>g[maxn];
void dfs(int x,int fa)
{
dp[x][0]=0;
dp[x][1]=0;
dp[x][2]=1;
int flag=0;
int mini=inf;int dson=0;
if(g[x].size()==1 && g[x][0]==fa)
{
dp[x][1]=inf;return;
}
for(int i=0;i<g[x].size();i++)
{
int v=g[x][i];
if(v==fa) continue;
dfs(v,x);
dp[x][0]+=min(dp[v][1],dp[v][2]);//fa
int ans=min(dp[v][0],dp[v][1]);
ans=min(ans,dp[v][2]);
dp[x][2]+=ans;//self
if(dp[v][1]<dp[v][2])
{
dp[x][1]+=dp[v][1];
if(mini>dp[v][2])
{
mini=dp[v][2];
dson=dp[v][1];
}
}
else
{
flag=1;
dp[x][1]+=dp[v][2];
}
}
if(flag==0)
{
dp[x][1]+=mini-dson;
}
}
int main()
{
//freopen("input.txt","r",stdin);
int n,m,a,b;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1,-1);
int res=min(dp[1][1],dp[1][2]);
cout<<res<<endl;
}
}