티스토리 뷰

1. 문제 링크

https://www.acmicpc.net/problem/1733

 

1733번: 등번호

첫째 줄에 티셔츠의 개수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 이후 N개의 행에 각 티셔츠의 정보가 두 개의 자연수로 주어진다. 이는 티셔츠의 안쪽과 바깥쪽에 적힌 등번호이다. 각 등번호는 1이상

www.acmicpc.net

2. 문제 개요

한 선수가 최대 두 가지의 번호를 부여받을 수 있다. 각 선수들이 어떤 번호를 선택해야 모든 선수들의 번호가 중복되지 않을 수 있을지 구하는 문제.

 

3. 문제 힌트

일반적인 O(VE)시간복잡도의 이분 매칭으로는 시간 초과다. 호프 크로프트 카프 알고리즘 O(V^(1/2) E)을 사용하자.

그리고 불가능하다면 불가능한 선수만 -1로 출력하지말고 전체 출력을 -1로 해줘야 한다(맞왜틀..)

 

4. 문제 풀이

N을 입력받고 각 행번째의 선수들이 부여받을 수 있는 번호를 vector에 저장하자.

그리고 알고리즘을 구현해서 실행하면 된다.

호프 크로프트 카프 알고리즘은 alternating path를 찾는 게 핵심이다.

 

5. 코드

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int INF = 987654321;
int n, match;
vector<vector<int>> adj;
vector<int> xy, yx, label;
void bfs()
{
queue<int> q;
for (int i = 1; i <= n; ++i) {
if (xy[i] == -1) {
label[i] = 0;
q.push(i);
}
else
label[i] = INF;
}
while (!q.empty()) {
int cur = q.front(); q.pop();
for (int next : adj[cur]) {
if (yx[next] != -1 && label[yx[next]] == INF) {
label[yx[next]] = label[cur] + 1;
q.push(yx[next]);
}
}
}
return;
}
bool dfs(int cur)
{
for (int next : adj[cur]) {
if (yx[next] == -1 || (label[yx[next]] == label[cur] + 1 && dfs(yx[next]))) {
yx[next] = cur;
xy[cur] = next;
return true;
}
}
return false;
}
int main()
{
scanf("%d", &n);
adj.resize(n + 1);
for (int i = 1; i <= n; ++i) {
int t1, t2;
scanf("%d %d", &t1, &t2);
if (t1 != t2) {
adj[i].push_back(t1);
adj[i].push_back(t2);
}
else
adj[i].push_back(t1);
}
xy.resize(n + 1, -1);
yx.resize(1000001, -1);
label.resize(n + 1);
while (1) {
bfs();
int flow = 0;
for (int i = 1; i <= n; ++i)
if (xy[i] == -1 && dfs(i))
flow++;
if (flow == 0) break;
match += flow;
}
if (match < n)
printf("-1\n");
else
for (int i = 1; i <= n; ++i)
printf("%d\n", xy[i]);
return 0;
}

6. 결과

 

지적, 댓글 환영입니다~.

댓글
«   2025/04   »
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
Total
Today
Yesterday