BOJ 11724 연결 요소의 개수
출처 : https://www.acmicpc.net/problem/11724
아 먼저 참고할건 이 글은 문제 풀이랑은 상관이 없다.(맨 밑에 정답코드는 넣었다.)
입력을 한번 보자 vn, en이 먼저 주어지고 아래 무방향 엣지 정보인 u v가 주어진다.
여기서 우리는 그래프를 표현해야되는데 가장 짜증 나는건 나는 'C'로 문제를 푼다는 것이다.
Q. 인접행렬로 그래프 표현해 쉽자나
A. 가오떨어지게 그게 뭐임
그래서 인접리스트를 만들어야 하는데
#define max 1000
struct node
{
int num;
struct node * next, *pre;
};
struct node *head[max + 1], *tail[max + 1];
int size[max + 1];
void push(int, int);
.
.
.
아 ㅋㅋㅋㅋㅋㅋㅋ 이거 언제 다 치고 있음 ㅋㅋㅋㅋㅋㅋㅋㅋ
(나 연결리스트 짤줄 안다. ㄹㅇ)
그래서 생각한게 'malloc, calloc, realloc 이거 싹다 사용하면 가능하겠다.' 이다.
#include<stdio.h>
#include<malloc.h>
int **elist, *eindex, vn, en;
int answer;
int make_answer();
int main(void)
{
answer = make_answer();
printf("%d\n", answer);
return 0;
}
int make_answer()
{
int a, b;
scanf("%d %d", &vn, &en);
/*
calloc 하면 0으로 밀어버리니깐
지금 값을 봤을땐 0 (NULL)이면 할당 안된 상태
*/
elist = (int **)calloc(vn + 1, sizeof(int*));
eindex = (int *)calloc(vn + 1, sizeof(int));
while (en--)
{
scanf("%d %d", &a, &b);
if (elist[a]) // NULL이 아닌 상태 -> 이미 malloc 한번 했으니깐 이젠 realloc 해야지
{
elist[a] = (int *)realloc(elist[a], sizeof(int) * (eindex[a] + 1));
}
else // NULL이니깐 처음엔 말록해야지
{
elist[a] = (int *)malloc(sizeof(int));
}
elist[a][eindex[a]++] = b;
if (elist[b])
{
elist[b] = (int *)realloc(elist[b], sizeof(int) * (eindex[b] + 1));
}
else
{
elist[b] = (int *)malloc(sizeof(int));
}
elist[b][eindex[b]++] = a;
}
}
malloc, calloc, realloc 뭔지 대충알고 주석 읽어보면 내가 왜 저짓을 해놨는지 이해가 갈것이다.
근데 좀더 찾아보니깐 'realloc의 첫번째 인자가 NULL이면 malloc과 동일하게 동작한다.'
라는걸 찾았음!!!!
이제 이걸사용하면 코드가 절반가량 줄어든다.
#include<stdio.h>
#include<malloc.h>
int **elist, *eindex, vn, en;
int answer;
void pb(int, int);
int make_answer();
int main(void)
{
answer = make_answer();
printf("%d\n", answer);
return 0;
}
int make_answer()
{
int a, b;
scanf("%d %d", &vn, &en);
elist = (int **)calloc(vn + 1, sizeof(int*));
eindex = (int *)calloc(vn + 1, sizeof(int));
while (en--)
{
scanf("%d %d", &a, &b);
pb(a, b);
pb(b, a);
}
// 해제
for (i = 0; i < vn + 1; i++)
{
if (elist[i]) // 이거 if문 넣자
{
free(elist[i]);
}
}
free(elist);
free(eindex);
}
void pb(int a, int b)
{
elist[a] = (int *)realloc(elist[a], sizeof(int) * (eindex[a] + 1));
elist[a][eindex[a]++] = b;
}
아 이제 우리는 꽤나 간편하게 그래프를 인접리스트로 구현할수 있게 되었다!!!!
사실 이쯤 글 읽는 정상적인 사람이면 'C++ 쓰지 븅신 ㅋㅋㅋ' 이라는 생각을 할것이다.
맞는말이다. 나도 동의 ㅋ
또 궁금한 사람도 있을것이다.
Q. tle 혹은 rte 난적은 없나?
A. 우선 내 수준에서 푸는 문제에 한해서는 전혀없다.
Q. 이거 말고는 다른 방법은 없나??
A. 물론 있다.(한번 해보고 때려치움) u, v쌍을 저장하는 구조체를 정렬한 뒤 하한, 상한 범위내에서 엣지를 보면 된다. 그치만 정렬, 상한, 하한 구현하는 것보다는 이게 훨씬 편하지 않은가?? ;)
bfs 혹은 dfs 혹은 union-find 아래 풀이는 dfs 이다.
#include<stdio.h>
#include<malloc.h>
int **elist, *eindex, vn, en, *memo;
int answer;
void go(int);
void pb(int, int);
int make_answer();
int main(void)
{
answer = make_answer();
printf("%d\n", answer);
return 0;
}
int make_answer()
{
int i, a, b;
scanf("%d %d", &vn, &en);
elist = (int **)calloc(vn + 1, sizeof(int*));
eindex = (int *)calloc(vn + 1, sizeof(int));
memo = (int *)calloc(vn + 1, sizeof(int));
while (en--)
{
scanf("%d %d", &a, &b);
pb(a, b);
pb(b, a);
}
for (i = 1, a = 0; i <= vn; i++)
{
if (!memo[i])
{
a++;
memo[i]++;
go(i);
}
}
// 해제
for (i = 0; i < vn + 1; i++)
{
if (elist[i])
{
free(elist[i]);
}
}
free(elist);
free(eindex);
free(memo);
return a;
}
void pb(int a, int b)
{
elist[a] = (int *)realloc(elist[a], sizeof(int) * (eindex[a] + 1));
elist[a][eindex[a]++] = b;
}
void go(int cur)
{
int d, next;
for (d = 0; d < eindex[cur]; d++)
{
next = elist[cur][d];
if (!memo[next])
{
memo[next]++;
go(next);
}
}
}