Skip to main content

Bipartite_Graph

BOJ 18214 Reordering the Documents

·719 words·4 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/18214 λ²ˆμ—­ 문제 λ²ˆμ—­ # Susan은 식탁 μ •λ¦¬λŠ” μž˜ν•˜μ§€λ§Œ, 사무싀 책상 μ •λ¦¬λŠ” 잘 λͺ»ν•©λ‹ˆλ‹€. Susan은 방금 일련의 λ¬Έμ„œλ“€μ— λŒ€ν•œ μ„œλ₯˜ μž‘μ—…μ„ 마쳀고, λ¬Έμ„œλ“€μ€ μ—¬μ „νžˆ 책상에 μŒ“μ—¬ μžˆμŠ΅λ‹ˆλ‹€. λ¬Έμ„œλ“€μ€ μΌλ ¨λ²ˆν˜Έκ°€ 있으며, 상사가 가져왔을 λ•ŒλŠ” μˆœμ„œλŒ€λ‘œ μŒ“μ—¬ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ§€κΈˆμ€ μˆœμ„œκ°€ μ™„λ²½ν•˜μ§€ μ•Šμ€λ°, Susan이 λ„ˆλ¬΄ κ²Œμ„λŸ¬μ„œ λ”λ―Έμ—μ„œ λΉ μ Έλ‚˜μ˜¨ λ¬Έμ„œλ“€μ„ μ œμžλ¦¬μ— λ‹€μ‹œ λ„£μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. μž‘μ—…μ΄ λλ‚¬λ‹€λŠ” μ†Œμ‹μ„ λ“£κ³ , μƒμ‚¬λŠ” κ·Έλ…€μ—κ²Œ 보내고 μžˆλŠ” λ¬Έμ„œ μƒμžμ— λ¬Έμ„œλ“€μ„ μ¦‰μ‹œ λ°˜λ‚©ν•˜κΈ°λ₯Ό μ›ν•©λ‹ˆλ‹€. λ¬Όλ‘  λ¬Έμ„œλ“€μ€ 일련번호 μˆœμ„œλŒ€λ‘œ μƒμžμ— λ³΄κ΄€λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

BOJ 23569 Friendship Graphs

·537 words·3 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/23569 λ²ˆμ—­ 문제 λ²ˆμ—­ # 문제 μ„€λͺ… # μ‚¬λžŒλ“€ κ°„μ˜ μƒν˜Έμž‘μš©μ΄ μ£Όμ–΄μ§ˆ λ•Œ, 정점이 μ‚¬λžŒλ“€μ΄κ³  두 μ‚¬λžŒμ΄ μ„œλ‘œ 친ꡬ인 κ²½μš°μ—λ§Œ κ·Έλ“€ 사이에 간선이 μžˆλŠ” κ·Έλž˜ν”„λ₯Ό μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ κ·Έλž˜ν”„λ₯Ό μ†Œμ…œ λ„€νŠΈμ›Œν¬λΌκ³  ν•˜λ©°, 예λ₯Ό λ“€μ–΄ λŒ€ν•™μ˜ ν•™μƒλ“€μ΄λ‚˜ μž‘μ€ λ§ˆμ„μ˜ μ£Όλ―Όλ“€κ³Ό 같은 λͺ¨λ“  μ‚¬λžŒλ“€μ˜ 집합에 λŒ€ν•΄ 잘 μ •μ˜λ©λ‹ˆλ‹€. 졜근 λͺ‡ λ…„κ°„ μ†Œμ…œ λ„€νŠΈμ›Œν¬λ₯Ό λΆ„μ„ν•˜λŠ” μ™„μ „ν•œ κ³Όν•™ λΆ„μ•Όκ°€ μƒκ²¨λ‚¬λŠ”λ°, μ΄λŠ” μ‚¬λžŒλ“€κ³Ό κ·Έλ“€μ˜ 행동에 λŒ€ν•œ λ§Žμ€ ν₯미둜운 츑면듀이 이 친ꡬ 관계 κ·Έλž˜ν”„μ˜ μ†μ„±μœΌλ‘œ κ°€μž₯ 잘 μ΄ν•΄λ˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

BOJ 1154 νŒ€ νŽΈμ„±

·254 words·2 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/1154 🧐 κ΄€μ°° 및 μ ‘κ·Ό # A / BνŒ€μœΌλ‘œ λ‚˜λˆ„λŠ”κ±Έ 보면 λ‹Ήμ—°νžˆ μ΄λΆ„κ·Έλž˜ν”„λ₯Ό λ– μ˜¬λ¦΄ 수 μžˆκ² λŠ”λ°.. 같은 그룹의 ν•™μƒλ“€λΌλ¦¬λŠ” λͺ¨λ‘ μ„œλ‘œ μ•„λŠ” 사이여야 ν•œλ‹€? μš°λ¦¬κ°€ μ•„λŠ” μ΄λΆ„κ·Έλž˜ν”„μ˜ μ •μ˜λž‘ λ­”κ°€ λŠλ‚Œμ΄ λ‹€λ₯΄λ‹€! μ € 말을 λ‹€μ‹œν•œλ²ˆ μƒκ°ν•΄λ³΄μž 같은 그룹의 학생이닀 -> μ„œλ‘œ μ•„λŠ”μ‚¬μ΄μ΄λ‹€ 이 λ¬Έμž₯의 λŒ€μš°λͺ…μ œλŠ”? μ„œλ‘œ λͺ¨λ₯΄λŠ” 사이이닀 -> λ‹€λ₯Έ 그룹의 학생이닀 κ·Έλ ‡λ‹€λ©΄, κ·Έλž˜ν”„μ˜ 간선을 λ’€μ§‘μ–΄λ²„λ¦¬μž! $N$은 μ΅œλŒ€ 1000μ΄λ―€λ‘œ, κ°„μ„  $M = N^2$κ°œλŠ” μΆ©λΆ„νžˆ 계산할 수 μžˆλ‹€. μ΄λ ‡κ²Œ 간선을 뒀집은 κ·Έλž˜ν”„λ₯Ό μ—¬ κ·Έλž˜ν”„, ν˜Ήμ€ complement graph라고 ν•œλ‹€. πŸ’» 풀이 # μ½”λ“œ (C++): void solve(){ cin >> N; while(1){ int u, v; cin >> u >> v; if(u == -1 && v == -1) break; know[u][v] = know[v][u] = true; } bool isBipartite = true; vector<int> color(N+1, 0); rep(i, 1, N+1) if(color[i] == 0){ queue<int> Q; Q.push(i); color[i] = 1; while(!Q.empty()){ int cur = Q.front(); Q.pop(); rep(nxt, 1, N+1){ if(cur == nxt) continue; if(know[cur][nxt]) continue; if(color[nxt] == 0){ color[nxt] = (color[cur] == 1 ? 2 : 1); Q.push(nxt); } else if(color[nxt] == color[cur]){ isBipartite = false; break; } } } } if(!isBipartite){ cout << -1; return; } vector<int> team1, team2; rep(i, 1, N+1){ if(color[i] == 1) team1.push_back(i); else team2.push_back(i); } cout << 1 << "\n"; for(auto x: team1) cout << x << " "; cout << -1 << "\n"; for(auto x: team2) cout << x << " "; cout << -1 << "\n"; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금

BOJ 23086 두 반으둜 λ‚˜λˆ„κΈ°

·335 words·2 mins
πŸ“ 문제 정보 # 링크: https://www.acmicpc.net/problem/23086 🧐 κ΄€μ°° 및 μ ‘κ·Ό # κ·Έλž˜ν”„μ™€ 간선이 μ£Όμ–΄μ‘Œμ„λ•Œ, νŠΉμ • μ‹œμ μ— 이뢄 κ·Έλž˜ν”„μΈκ°€?λ₯Ό μ°ΎλŠ” λ¬Έμ œμ΄λ‹€. μ΄λΆ„κ·Έλž˜ν”„λ₯Ό νŒμ •ν•˜λŠ”λ°μ—λŠ” $O(N+M)$의 μ‹œκ°„μ΄ κ±Έλ¦°λ‹€. μ§κ΄€μ μœΌλ‘œ 생각해보면, λ¦¬μŠ€νŠΈμ— 쓰인 μ°¨λ‘€λŒ€λ‘œ μΉœν•œ 친ꡬλ₯Ό μ ˆκ΅μ‹œν‚¬ 수 μžˆμœΌλ―€λ‘œ, 리슀트λ₯Ό λ’€μ§‘μ–΄μ„œ ν•˜λ‚˜μ”© 간선을 이어가며 ν•΄λ‹Ή κ·Έλž˜ν”„κ°€ 이뢄 κ·Έλž˜ν”„μΈμ§€ νŒμ •ν•˜λŠ” 방법을 μ“Έ 수 μžˆμ„ 것이닀. μ΄λ•Œ μ‹œκ°„ λ³΅μž‘λ„λŠ” $O(K(N+M))$이닀. μ΄λŠ” λ„ˆλ¬΄ λŠλ¦¬λ‹€! 문제 상황을 쑰금 더 κ΄€μ°°ν•΄λ³΄μž. $\text{ans}$개의 μΉœν•œ 친ꡬ μŒμ„ μ ˆκ΅μ‹œμΌœ 이뢄 κ·Έλž˜ν”„κ°€ μ„±λ¦½ν•˜λ„λ‘ ν–ˆλ‹€λ©΄, $\text{ans}+1$개의 μŒμ„ μ ˆκ΅μ‹œμΌ°μ„λ•Œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ μ΄λΆ„κ·Έλž˜ν”„μΌ 것이닀. $0 \leq a \leq K$인 $a$에 λŒ€ν•΄, μ΄λΆ„κ·Έλž˜ν”„κ°€ μ„±λ¦½ν•˜λŠ”μ§€λŠ” 단쑰성이 μ‘΄μž¬ν•œλ‹€! **λ§€κ°œλ³€μˆ˜ 탐색(νŒŒλΌλ©”νŠΈλ¦­ μ„œμΉ˜)**κ°€ κ°€λŠ₯ν•˜λ‹€. πŸ’» 풀이 # μ½”λ“œ (C++): int N, M, K; vector<pair<int, int>> links[100010]; // (nxt, idx) vector<int> prohibit_list; int color[100010]; // 0: unvisited, 1: group A, 2: group B bool prohibited[200010]; bool isBipartite(int cnt){ rep(i, 1, M+1) prohibited[i] = false; rep(i, 0, cnt) prohibited[prohibit_list[i]] = true; rep(i, 1, N+1) color[i] = 0; rep(i, 1, N+1) if(color[i] == 0){ queue<int> Q; Q.push(i); color[i] = 1; while(!Q.empty()){ int cur = Q.front(); Q.pop(); for(auto [nxt, idx]: links[cur]){ if(prohibited[idx]) continue; if(color[nxt] == 0){ color[nxt] = (color[cur] == 1 ? 2 : 1); Q.push(nxt); } else if(color[nxt] == color[cur]){ return false; } } } } return true; } void solve(){ cin >> N >> M >> K; rep(i, 1, M+1){ int u, v; cin >> u >> v; links[u].push_back({v, i}); links[v].push_back({u, i}); } rep(i, 0, K){ int p; cin >> p; prohibit_list.push_back(p); } // λͺ¨λ‘ κΈˆμ§€ν–ˆμ„λ•Œ 이뢄 κ·Έλž˜ν”„μΈκ°€? if(!isBipartite(K)){ cout << -1; return; } // νŒŒλΌλ©”νŠΈλ¦­ μ„œμΉ˜ int ok = K, ng = -1; while(ok - ng > 1){ int mid = (ok + ng) >> 1; if(isBipartite(mid)) ok = mid; else ng = mid; } cout << ok << "\n"; int groupA_sz = 0, groupB_sz = 0; isBipartite(ok); rep(i, 1, N+1) color[i] == 1 ? groupA_sz++ : groupB_sz++; cout << min(groupA_sz, groupB_sz) << ' ' << max(groupA_sz, groupB_sz) << "\n"; } πŸ”’ κ΅¬ν˜„ μ½”λ“œ 잠금