#include #include #include using namespace std; int N; vector > sousedi; vector visited; vector A, B; int cyklus_a, cyklus_b; // Prohledávání do hloubky pro nalezení cyklu v původním grafu void dfs_najdi_cyklus(int v, int parent) { if (visited[v]) { cyklus_a = v; cyklus_b = parent; return; } visited[v] = 1; for (unsigned i = 0; i < sousedi[v].size(); i++) { int c = sousedi[v][i]; if (c == parent) continue; dfs_najdi_cyklus(c, v); if (cyklus_a != -1 && cyklus_b != -1) return; } } // Vypočítá pro vrchol v hodnoty A[v] a B[v] void vypocitej_vrchol(int v, int parent) { B[v] = 0; for (unsigned i = 0; i < sousedi[v].size(); i++) { int c = sousedi[v][i]; if (c == parent) continue; vypocitej_vrchol(c, v); B[v] += A[c]; } A[v] = B[v]; for (unsigned i = 0; i < sousedi[v].size(); i++) { int u = sousedi[v][i]; if (u == parent) continue; A[v] = max(A[v], B[v] - A[u] + (1 + B[u])); } } // Zjistí velikost maximálního párování za předpokladu, že graf neobsahuje cykly int maximum_na_stromech() { A.assign(N, -1); B.assign(N, -1); int vysledek = 0; for (int v = 0; v < N; v++) { if (A[v] == -1 && B[v] == -1) { vypocitej_vrchol(v, -1); vysledek += A[v]; } } return vysledek; } void vyrad_z_vectoru(vector& v, int hodnota) { vector::iterator pozice = find(v.begin(), v.end(), hodnota); if (pozice != v.end()) v.erase(pozice); } int main() { cin >> N; sousedi.resize(N); visited.resize(N, 0); for (int i = 0; i < N; i++) { int a, b; cin >> a >> b; a--; b--; sousedi[a].push_back(b); sousedi[b].push_back(a); } // Najdeme nějaké dva vrcholy, které jsou v cyklu a sousedí cyklus_a = cyklus_b = -1; dfs_najdi_cyklus(0, -1); // Možnost 1: hranu (cyklus_a, cyklus_b) nevybereme do párování // (takže ji můžeme z grafu hned odstranit a zůstane jen strom) vyrad_z_vectoru(sousedi[cyklus_a], cyklus_b); vyrad_z_vectoru(sousedi[cyklus_b], cyklus_a); int moznost1 = maximum_na_stromech(); // Možnost 2: hranu (cyklus_a, cyklus_b) vybereme do párování // (takže ostatní s nimi ani nemusí sousedit a zůstane jen les) for (int i = 0; i < N; i++) { vyrad_z_vectoru(sousedi[i], cyklus_a); vyrad_z_vectoru(sousedi[i], cyklus_b); } sousedi[cyklus_a].clear(); sousedi[cyklus_a].push_back(cyklus_b); sousedi[cyklus_b].clear(); sousedi[cyklus_b].push_back(cyklus_a); int moznost2 = maximum_na_stromech(); cerr << cyklus_a << "," << cyklus_b << " " << moznost1 << "," << moznost2 << endl; int vysledek = max(moznost1, moznost2); cout << vysledek << endl; }