νμ΄
- μ ν μκ° λ΄μ νμ§ λͺ»νμΌλ©° ν΄λ΅μ μ°Έκ³ νμλ€.
- μλΌν μ€ν λ€μ€μ 체λ μ΄λ²μμΌ λΉλ‘μ μ΄ν΄λ₯Ό μ’ ν λ― νλ€.
- DFSλ‘ νμ΄μΌ νλ κ²μ λ§μ§λ§ DPλ₯Ό μ μ©νλ λΆλΆμμ μ ν κ°μ΄ μ‘νμ§ μμμλ€.
- DP λΆλΆμ νμ¬ λ Έλμ μν κ°μ νμ λ Έλλ€μ μνκ°μ μ΄μ©ν΄μ λ§λ€μ΄μΌ νλ€.
- μν κ°μ prime nodeκ° ν¬ν¨λμ§ μμ κ²½μ°
curr[0]
μ ν¬ν¨λ κ²½μ°curr[1]
λ₯Ό λ°λ‘ μΆμ ν΄μΌ νλ€. - νμ¬ λ Έλκ° primeμ΄λΌλ©΄
- prime nodeκ° ν¬ν¨λ κ²½μ°μ μ
curr[1]
μ νμ λ Έλ μ€ prime nodeκ° ν¬ν¨ μλ κ²½μ°μ μnext[0]
λ§ μΆκ°ν΄μΌ νλ€. - νμ λ Έλ μ€ prime nodeκ° ν¬ν¨λ κ²½μ°μ μλ ν¬ν¨μν¬ μ μλ€. μλνλ©΄ κ·Έλ κ² λλ©΄ prime nodeκ° 2κ° μ΄μ ν¬ν¨λ κ²½λ‘κ° λκΈ° λλ¬Έμ΄λ€.
- νμ¬ λ Έλκ° primeμ΄ μλλΌλ©΄
- prime nodeκ° ν¬ν¨λμ§ μμ κ²½μ°μ μ
curr[0]
μ νμ λ Έλ μ€ prime nodeκ° ν¬ν¨ μλ κ²½μ°μ μnext[0]
λ₯Ό μΆκ°νλ€. - prime nodeκ° ν¬ν¨λ κ²½μ°μ μ
curr[1]
μλ νμ λ Έλ μ€ prime nodeλ₯Ό ν¬ν¨ν κ²½μ°μ μnext[1]
λ₯Ό μΆκ°νλ€.
- μ μΌ μ΄ν΄κ° μ΄λ €μ λ λΆλΆμ κ²½λ‘μ μλ₯Ό κ³μ°νλ λΆλΆμ΄μλλ° μλμ κ°μ΄ κ³μ°ν μ μλ€.
- νμ¬ λ Έλκ° prime nodeλΌλ©΄
- νμ λ
Έλ μ€ prime nodeκ° μλ κ²½μ°μ μ
next[0]
λ₯Ό λͺ¨λ κ²°κ³Όκ°μ λνλ€. - κ·Έλ¦¬κ³ νμ λ
Έλ μ€ 2κ°λ₯Ό μ ν (combination) νμ¬ κ°κ° prime nodeκ° μλ κ²½μ°μ μ
next[0]
λ₯Ό ꡬνμ¬ κ³±ν λ€ κ²°κ³Όκ°μ λνλ€. - prime nodeλ₯Ό ν¬ν¨νμ§ μλ λ κ²½λ‘ + νμ¬ λ Έλ (prime)λ₯Ό ν©ν κ²λ μλ‘μ΄ κ²½λ‘κ° λλ€.
- νμ¬ λ Έλκ° prime nodeκ° μλλΌλ©΄
- νμ λ
Έλ μ€ prime nodeμΈ κ²½μ°μ μ
next[1]
λ₯Ό λͺ¨λ κ²°κ³Όκ°μ λνλ€. - κ·Έλ¦¬κ³ νμ λ
Έλ μ€ 2κ°λ₯Ό μ ν (combination)νμ¬ νμͺ½μ prime nodeλ₯Ό ν¬ν¨ν κ²½μ°
next[0]
, λ€λ₯Έμͺ½μ prime nodeλ₯Ό ν¬ν¨νμ§ μμ κ²½μ°next[1]
λ₯Ό μ ννμ¬ κ³±ν λ€ κ²°κ³Όκ°μ λνλ€. - prime nodeλ₯Ό ν¬ν¨νλ κ²½λ‘ + νμ¬ λ Έλ (not prime) + prime nodeλ₯Ό ν¬ν¨νμ§ μλ κ²½λ‘λ₯Ό ν©ν κ²λ μλ‘μ΄ κ²½λ‘κ° λλ€.
- κ·Όλ° μμ λ΄μ©μ κ·Έλλ‘ κ΅¬ννκ² λλ©΄ timeoutμ΄ λ°μνκ² λλ€.
- μμ λ΄μ©μ μλ κ·Έλλ‘ κ΅¬ννκ²μ νλ¨μ μΆκ°λ‘ λΆμ¬λμλ€.
Β
class Solution { public: vector<bool> get_prime_table(int n) { vector<bool> result(n + 1); fill(result.begin(), result.end(), true); result[0] = result[1] = false; int p = 2; while (p <= n) { if (!result[p]) ++p; int c = p + p; while (c <= n) { result[c] = false; c += p; } ++p; } return result; } array<long long, 2> dfs( unordered_map<int, vector<int>>& adj, vector<bool>& is_prime, int node, int parent, long long& result) { array<long long, 2> curr = {}; auto prime = is_prime[node]? 1 : 0; ++curr[prime]; for (auto child : adj[node]) { if (child == parent) continue; auto next = dfs(adj, is_prime, child, node, result); // non prime cases of others x prime cases of next result += curr[0] * next[1]; // prime cases of others x non prime cases of next result += curr[1] * next[0]; // add non prime cases curr[prime] += next[0]; // count prime cases if current is not prime if (!prime) curr[1] += next[1]; } return curr; } long long countPaths(int n, vector<vector<int>>& edges) { auto is_prime = get_prime_table(n); unordered_map<int, vector<int>> adj; for (auto& edge : edges) { adj[edge[0]].push_back(edge[1]); adj[edge[1]].push_back(edge[0]); } long long result = 0; dfs(adj, is_prime, 1, -1, result); return result; } };
DFSλ₯Ό μ€λͺ κ·Έλλ‘ κ΅¬ννλ©΄?
- dfs λΆλΆμ μ€λͺ κ·Έλλ‘ κ΅¬νν κ²μ μλμ κ°λ€.
- νμ λ Έλ 2κ°μ μ‘°ν©μ λ°λΌ κ³μ°νλ λΆλΆμ΄ μΆκ°λμκ³ μ΄λ‘ μΈν΄μ μκ° μ νμ κ±Έλ¦¬κ² λλ€.
- μ΅μ
μ κ²½μ° νμ λ
Έλκ°
n
μ κ·Όμ ν μ«μκ° λλ©΄ λ§νΌμ μ°μ°μ μνν΄μΌ νκΈ° λλ¬Έμ΄λ€.
array<long long, 2> dfs( unordered_map<int, vector<int>>& adj, vector<bool>& is_prime, int node, int parent, long long& result) { array<long long, 2> curr = {}; auto prime = is_prime[node]? 1 : 0; ++curr[prime]; // tracking current states vector<array<long long, 2>> nexts; for (auto child : adj[node]) { if (child == parent) continue; auto next = dfs(adj, is_prime, child, node, result); nexts.push_back(next); // add non prime cases curr[prime] += next[0]; // count prime cases if current is not prime if (!prime) curr[1] += next[1]; } // calculate result (n^2 time complexity!!!) int M = nexts.size(); if (prime) { for (auto& next : nexts) { result += next[0]; } for (int i = 0; i < M - 1; ++i) { for (int j = i + 1; j < M; ++j) { result += nexts[i][0] * nexts[j][0]; } } } else { for (auto& next : nexts) { result += next[1]; } for (int i = 0; i < M - 1; ++i) { for (int j = i + 1; j < M; ++j) { result += nexts[i][0] * nexts[j][1]; result += nexts[i][1] * nexts[j][0]; } } } return curr; }
μ΅μ ν νκΈ°
- μκ° μ΄κ³Όλ₯Ό λ°μμν€λ μ΄μ λ λ νμ λ Έλμ κ°μ κ³±ν΄μ λνλ κ²μ μκ° λ³΅μ‘λκ° μ΄κΈ° λλ¬Έμ΄λ€. λ°λΌμ μ΄ λΆλΆμ μ΅μ ννλ€.
- μ΄λ€ μ§ν© κ° μμ λ μ§ν©μμ 2κ°μ μ«μλ₯Ό 골λΌμ κ³±ν κ°μ ν©μ λ€μκ³Ό κ°μ΄ ꡬν μ μλ€.
- λ°λΌμ κ° νλͺ©μ ν©μ μΆμ νλ λ³μ
sum
μ νμ¬ κ°a[i]
μ κ³±νμ¬ κ²°κ³Όμ λνλ©΄result += sum * a[i]
2κ°μ μ«μλ₯Ό 골λΌμ κ³±ν κ°μ ν©μ΄ λλ€.
array<long long, 2> dfs( unordered_map<int, vector<int>>& adj, vector<bool>& is_prime, int node, int parent, long long& result) { array<long long, 2> curr = {}; auto prime = is_prime[node]? 1 : 0; ++curr[prime]; // tracking current states vector<array<long long, 2>> nexts; for (auto child : adj[node]) { if (child == parent) continue; auto next = dfs(adj, is_prime, child, node, result); nexts.push_back(next); // add non prime nodes curr[prime] += next[0]; // count prime nodes if current is not prime if (!prime) curr[1] += next[1]; } // calculate result if (prime) { // add non prime cases for (auto& next : nexts) { result += next[0]; } // add multiplication of two non prime cases long long nonPrimeSum = 0; for (auto& next : nexts) { result += nonPrimeSum * next[0]; nonPrimeSum += next[0]; } } else { // add prime cases for (auto& next : nexts) { result += next[1]; } // add multiplication of prime cases & non prime cases long long nonPrimeSum = 0; long long primeSum = 0; for (auto& next : nexts) { result += nonPrimeSum * next[1]; result += primeSum * next[0]; nonPrimeSum += next[0]; primeSum += next[1]; } } return curr; }
- μ’ λ μ΅μ ν νμλ©΄ sum λ‘μ§μ μλμ²λΌ ν©μΉ μ μλ€.
// calculate result int notPrime = prime == 1? 0 : 1; for (auto& next : nexts) { result += next[notPrime]; } array<long long, 2> sum = {0, 0}; for (auto& next : nexts) { result += sum[0] * next[1]; result += sum[1] * next[0]; sum[prime] += next[0]; if (!prime) sum[1] += next[1]; } return curr;
- λ μ΅μ ν νλ©΄ μλμ κ°λ€.
// calculate result array<long long, 2> sum = {0, 0}; ++sum[prime]; for (auto& next : nexts) { result += sum[0] * next[1]; result += sum[1] * next[0]; sum[prime] += next[0]; if (!prime) sum[1] += next[1]; } return curr;
- μ¬κΈ°μ μ’ λ μ΅μ ννλ©΄ nextsλ₯Ό μ κ±°ν μ μλ€. μ κ±°ν κ²°κ³Όλ λ³Έ νμ΄μ§ μ²μμ μλ μ루μ μ μ°Έκ³ νλ©΄ λλ€.