#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<sstream> #include<algorithm> #include<queue> #include<deque> #include<iomanip> #include<vector> #include<cmath> #include<map> #include<stack> #include<set> #include<functional> #include<fstream> #include<memory> #include<list> #include<string> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 31 #define MAXN 20000 + 9 #define INF 1000000009 #define eps 0.00000001 #define sf(a) scanf("%d",&a) /* N台电脑构成树! 选点做服务器,最小支配集! 注意这里每个电脑只能从一台服务器上获得信息,说明不能有一个点和两个支配集的点相连! 所以dp[u][1]的状态就是不可行的! */ struct edge { int to, next; }E[MAXN*2]; int head[MAXN]; int cnt, n, dp[MAXN][3]; void init() { cnt = 0; memset(dp, 0, sizeof(dp)); memset(head, -1, sizeof(head)); } void addedge(int u, int v) { E[cnt].to = v; E[cnt].next = head[u]; head[u] = cnt++; } void Dp(int u, int p) { dp[u][0] = 1; dp[u][2] = 0; bool f = false; int sum = 0, inc = INF; for (int i = head[u]; i != -1; i = E[i].next) { int v = E[i].to; if (v == p) continue; Dp(v, u); dp[u][0] += min(dp[v][0], dp[v][2]); if (dp[v][0] < dp[v][1]) { f = true; sum += dp[v][0]; } else { inc = min(inc, dp[v][0] - dp[v][1]); sum += dp[v][1]; } if (dp[v][1] != INF&&dp[u][2] != INF) dp[u][2] += dp[v][1]; else dp[u][2] = INF; } if (inc == INF && !f) dp[u][1] = INF; else { dp[u][1] = sum; if (!f) dp[u][1] += inc; } } int main() { while (scanf("%d", &n) != EOF) { int f, t; init(); for (int i = 0; i < n - 1; i++) { scanf("%d%d", &f, &t); addedge(f, t); addedge(t, f); } Dp(1, -1); printf("%d ", min(dp[1][1], dp[1][0])); int flag; scanf("%d", &flag); if (flag == -1) break; } }