오랜만에 unordered_set 쓰는 특이한 문제였음.
핵심은 그리디하게 지워도 상관 없다는 점
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #include <iostream> #include <algorithm> #include <unordered_set> constexpr int MAXN = 200'004; constexpr int MAXQ = (1 << 18); int N, M; std::unordered_set<int> E[MAXN]; int Q[MAXQ], qf, qr; void clear() { for (int i = 0; i <= N; ++i) E[i].clear(); } int main() { using namespace std; ios::sync_with_stdio(false); cin.tie(nullptr); int tc; cin >> tc; for (int t = 1; t <= tc; ++t) { cin >> N >> M; clear(); for (int i = 0; i < M; ++i) { int x, y; cin >> x >> y; E[x].insert(y); E[y].insert(x); } qf = qr = 0; for (int i = 1; i <= N; ++i) { if (E[i].size() == 2) Q[qr++] = i; } int rm = 0; while (qf < qr) { const int np = Q[qf++]; if (E[np].size() != 2) continue; auto it = E[np].begin(); const int e1 = *it; const int e2 = *(++it); if (E[e1].find(e2) != E[e1].end()) { ++rm; E[e1].erase(np); E[e2].erase(np); if (E[e1].size() == 2) Q[qr++] = e1; if (E[e2].size() == 2) Q[qr++] = e2; } } cout << "Case #" << t << '\n' << (N - rm) << '\n'; } } |
이거 큐 빌때까지 degree 2인거 넣엇다 뺏다하는거임?
일단 degree 2 인거를 다 집어넣음
이게 문제의 조건을 만족하는지 확인하고 간선을 지움 -> 지우면 다시 degree 2인게 생겨남 -> 이걸 다시 큐에 집어넣음
그러면 아무리 많이봐도 정점의 개수만큼만 돌고 종료하게 됨
그 새로 생겨난 degree 2짜리는 어케탐색한거임? 지운거랑 연결된 애들 둘에서 탐색?
ㅇ
잘짜줘야겠네 그부분을...
지우면 degree가 2니까 단 2개만 degree가 바뀔거 아니야. 그거 2개만 확인해주면 되지
근데 큐 stl안쓰고 직접짠 이유가머임? 난 햇갈리던데 저러면
STL 큐 가끔씩 실수해서
저렇게 짤 때 있음
ㅇㅎ
제대로 된 정답은 속도 때문에 동적할당 하기가 싫어서... 가 맞은듯