구름톤 챌린지 4주 차 학습 일기 - 2
구름 이라는 곳에서 문제 풀이 챌린지(구름톤 챌린지)를 한다고 해서 참여 중이다. 이벤트 기간 동안 문제가 꾸준이 올라오며, 주에 2회씩 (혹은 그 이상) 챌린지 문제들에 대해 풀이가 가능한 문제들을 풀이해보고, 후기를 남겨보려고 한다.
글 관리 · 공개 범위구름톤 챌린지란?
구름 이라는 곳에서 문제 풀이 챌린지(구름톤 챌린지)를 한다고 해서 참여 중이다. 이벤트 기간 동안 문제가 꾸준이 올라오며, 주에 2회씩 (혹은 그 이상) 챌린지 문제들에 대해 풀이가 가능한 문제들을 풀이해보고, 후기를 남겨보려고 한다.
- 문제 푸는 곳: https://level.goorm.io/l/challenge/goormthon-challenge
- 학습 일기 작성 가이드: https://goorm.notion.site/5ad9e8eef00f4c19b083572c2000d7f8
- 풀이 사용 컨테이너(구름 컨테이너): https://goor.me/8jsC9vbx5TCeaCcRA
문제 풀이
- 문제 제목: 통신망 분석
- 문제 링크: https://level.goorm.io/exam/195699/%EA%B7%B8%EB%9E%98%ED%94%84%EC%9D%98-%EB%B0%80%EC%A7%91%EB%8F%84/quiz/1
- 문제 예상 티어: Gold V
풀이 접근
어제와 마찬가지로 나의 경우 Union Find로 접근했다. 같은 집합에 속하는 녀석들을 관리할 때는 이 방법이 제일 편하다.
풀이 과정은 아래와 같다.
- 입력을 받으면서 같은 집합에 속하는 애들을
merge한다 - 다시 처음부터 정점을 순회하면서
root를 확인해서, 처음 나오는root면 Component를 생성한다.- 현재 정점이 속한 Component에 해당 컴퓨터를 추가한다.
- Component 안에 속하는 컴퓨터들이 가진 간선의 갯수를 세서 반영한다.
- 문제에서 준 기준으로 Component를 정렬한다.
- 0번째 index의 Component의 원소들을 출력한다.
그래프를 다루는 법만 잘 알고 있다면 순수 구현 문제처럼 풀이가 된다.
주의해야할 점은 정렬할 때 인데, 밀도의 계산을 분수로 하게 되면 WA를 받기 쉽다. 이 경우 분수로 하기보다는 와 를 비교한다 할 때 와 를 비교하는 식으로 회피하면 실수 오차 없이 정렬할 수 있다. 또, 이 경우 문제 조건에서 수의 범위가 int 범위를 초과할 수 있으므로, long long을 사용해야 한다. (Worst 시 > 0x7FFFFFFF 이다)
시간 복잡도의 병목 부분은 정렬과 처음 간선 입력을 받는 부분이고, 이다.
내 풀이
#include <bits/stdc++.h>
using namespace std;
int N, M;
typedef long long ll;
struct UF {
int parent[100001];
UF() {
for(int i = 0; i <= 100000; ++i) parent[i] = i;
}
int getRoot(int v) {
if (v == parent[v]) return v;
return parent[v] = getRoot(parent[v]);
}
void merge(int a, int b) {
a = getRoot(a);
b = getRoot(b);
if (a == b) return;
parent[b] = a;
}
} uf;
vector<int> adj[100001];
struct Component {
ll numComputer;
ll numConnection;
vector<int> members;
bool operator<(const Component& t) const {
// 1. 커넥션 수 / 컴퓨터 수
// 2. 밀도 같으면 컴퓨터 적은 수
// 3. 더 작은 번호 컴퓨터 순
if (numComputer * t.numConnection != numConnection * t.numComputer) {
return numComputer * t.numConnection < numConnection * t.numComputer;
}
if (numComputer != t.numComputer) {
return numComputer < t.numComputer;
}
return members[0] < t.members[0];
}
} com[100000];
int main() {
scanf("%d %d", &N, &M);
for(int i = 0; i < M; ++i) {
int a, b; scanf("%d %d", &a, &b);
adj[a].push_back(b);
uf.merge(a, b);
}
int cid = 0;
map<int, int> uq;
for(int a = 1; a <= N; ++a) {
if (uq.find(uf.getRoot(a)) == uq.end()) {
uq[uf.getRoot(a)] = cid;
++cid;
}
int gid = uq[uf.getRoot(a)];
com[gid].members.push_back(a);
com[gid].numComputer++;
}
for(int c = 0; c < cid; ++c) {
ll cnt = 0;
for(auto& cur: com[c].members) {
cnt += adj[cur].size();
}
com[c].numConnection = cnt;
}
sort(com, com + cid);
for(auto& item: com[0].members) {
printf("%d ", item);
}
printf("\n");
return 0;
}이전 사이트에서 옮긴 글입니다. 원본 보관본
AI로 읽기 · Markdown
로그인 없이 읽는 Markdown 원문.
curl -fsSL 'https://www.readiz.com/blog/history/grt/grt-week4_2/index.md'