#include #include #include #include using namespace std; const int MAX = 110000; int N; vector tree[MAX]; /* Hopcroft-Karp の二部マッチング */ const int MAX_L = MAX; const int MAX_R = MAX; struct Graph { vector adj[MAX_L]; Graph() {} inline vector& operator [] (int i) { return adj[i]; } void addedge(int from, int to) { adj[from].push_back(to); } friend ostream& operator << (ostream& s, const Graph& G) { s << endl; for (int i = 0; i < MAX_L; ++i) { if (G.adj[i].empty()) continue; s << i << " : "; for (int j = 0; j < G.adj[i].size(); ++j) { s << G.adj[i][j] << ", "; } } return s; } }; Graph G; static int L = 0; // ここに左ノードの使いたい頂点数をセット static bool seen[MAX_L]; static bool matched[MAX_L]; static int level[MAX_L]; static int matching[MAX_R]; void hobfs(Graph &G) { queue que; for (int left = 0; left < L; ++left) { level[left] = -1; if (!matched[left]) { que.push(left); level[left] = 0; } } level[L] = L; while (!que.empty()) { int left = que.front(); que.pop(); for (int i = 0; i < G[left].size(); ++i) { int right = G[left][i]; int next = matching[right]; if (level[next] == -1) { level[next] = level[left] + 1; que.push(next); } } } } bool hodfs(Graph &G, int left) { if (left == L) return true; if (seen[left]) return false; seen[left] = true; for (int i = 0; i < G[left].size(); ++i) { int right = G[left][i]; int next = matching[right]; if (level[next] > level[left] && hodfs(G, next)) { matching[right] = left; return true; } } return false; } int Hopcroft_Karp(Graph &G) { for (int i = 0; i < MAX_R; ++i) matching[i] = L; memset(matched, 0, sizeof(matched)); int res = 0; while (true) { hobfs(G); memset(seen, 0, sizeof(seen)); bool finished = true; for (int left = 0; left < L; ++left) { if (!matched[left] && hodfs(G, left)) { matched[left] = true; ++res; finished = false; } } if (finished) break; } return res; } /* ツリーを二部グラフに */ void rec(int v, int flag, int p = -1) { if (flag == 0) ++L; if (p != -1) { if (flag == 0) { G.addedge(v, p); } else { G.addedge(p, v); } } for (auto ch : tree[v]) { if (ch == p) continue; rec(ch, 1 - flag, v); } } int main() { cin >> N; for (int i = 0; i < N-1; ++i) { int u, v; cin >> u >> v; --u, --v; tree[u].push_back(v); tree[v].push_back(u); } /* ツリーは二部グラフなので「左」と「右」にわける */ rec(0, 0); /* 最大マッチングを求める */ int max_matching = Hopcroft_Karp(G); /* N - 最大マッチング */ cout << N - max_matching << endl; }