halang-log
💡 PS

[BOJ] 2406 안정적인 네트워크

date
May 3, 2022
slug
boj-2406
author
status
Public
tags
PS
크루스칼
summary
안정적인 네트워크 문제에 대한 풀이입니다.
type
Post
thumbnail
category
💡 PS
updatedAt
Aug 3, 2023 09:24 AM
언어

문제

풀이

크루스칼 알고리즘을 이용하여 문제를 풀었다.
p배열은 부모가 누구인지 알려주는 배열이다. (p[a] = b 라면 a의 부모는 b) find를 할 때 path compression(경로 압축)을 통해 parent를 찾아낸 루트로 바꿔 버리면 중복 연산을 방지한다.
본사 컴퓨터는 이미 연결되어 있기 때문에 adj배열에 푸쉬하지 않는다. 코스트 오름차순으로 정렬해주고 go함수에서 순차적으로 탐색하며 같은 그룹이 아니면 merge하고 ans벡터에 두 노드 정보를 저장한다. sm은 최소 비용이다.

코드

#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; typedef pair<int, int> pii; struct info{ int c, s, e; }; int n, m; vector<info> adj; vector<int> v[1000]; int p[1000], sm = 0; vector<pii> ans; int find(int a) { if (p[a] == -1) return a; return p[a] = find(p[a]); } void merge(int a, int b) { a = find(a), b = find(b); if (a == b) return; p[b] = a; } void go() { for(int i = 0; i < adj.size(); i++) { if (find(adj[i].s) == find(adj[i].e)) continue; merge(adj[i].s, adj[i].e); ans.push_back({adj[i].s, adj[i].e}); sm += adj[i].c; } } int main() { memset(p, -1, sizeof(p)); scanf("%d %d", &n, &m); for(int a, b, i = 0; i < m; i++) { scanf("%d %d", &a, &b); a--; b--; v[a].push_back(b); v[b].push_back(a); if (find(a) == find(b)) continue; merge(a, b); } for(int i = 0; i < n; i++) { for(int a, j = 0; j < n; j++) { scanf("%d", &a); if (i >= j or i == 0 or j == 0) continue; adj.push_back({a, i, j}); } } sort(adj.begin(), adj.end(), [](info a, info b) {return a.c < b.c;}); go(); printf("%d %d\n", sm, ans.size()); for(pii i : ans) printf("%d %d\n", i.first+1, i.second+1); }