ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 1197] 최소 스패닝 트리
    백준/최소 스패닝 트리 2023. 9. 16. 23:01

    그래프 이론 중 가장 대표적인 유형인 최소 신장 트리 문제

     

    여기서 중요한 것만 간략히 말하자면

     

    1. unordered_map으로 우선 간선과 정점 정보를 받고 vector로 변환해서 정렬하려고 하면 안됨

     

    처음에는 key-value 형식으로 받은 후에 vector로 바꿔서 정렬 후에 함수 인자로 넣어서

    돌리려고 했는데 이러면 문제가 발생함.

     

    만약 간선의 가중치가 같으면 map 특성 때문에 계속 해당 간선 key값이 최신화됨.

     

    예시를 들자면 1-2 cost = 3 이 있었는데 만약 3-5 cost = 3 이 들어오면 1-2 는 없어지고 3-5 에 대한 정보만 남는다는 거임.

    그래서 그냥 vector로 다 받아주면 된다.

     

    그러니까 이렇게 하면 안된다는 뜻임.

    unordered_map<int, pair<int, int>> info;
    
    //for문
    info[cost] = make_pair(a,b);

    이렇게 하면 map에서 각 key값은 중복될 수 없는 유일한 값이므로 계속해서 똑같은 cost에 대한 값이 들어오면 value에 있는 정점 정보 pair가 계속 최신화 된다는 뜻.

     


    2. kruskal 로 돌리는데 이때 중요한 것은 union find를 통해 isCycle 인지만 판단해주면 된다는 것

     

    작은 것부터 필요한 간선들만 선택해 적립해나가는 식이므로

    해당 간선을 포함시켰을때 cycle이 되는지만 판단해주면 된다.

     


    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    #define SIZE 10001
    
    using namespace std;
    
    vector<pair<int, pair<int, int>>> edges;
    
    int V, E;
    int parent[SIZE];
    
    int findParent(int x) {
    	if (parent[x] == x) return x;
    	else return parent[x] = findParent(parent[x]);
    }
    
    void updateParent(int a, int b) {
    	a = findParent(a);
    	b = findParent(b);
    
    	if (a != b) parent[b] = a;
    }
    
    bool isCycle(int a, int b) {
    	a = findParent(a);
    	b = findParent(b);
    
    	return a == b;
    }
    
    void solve() {
    	int ans = 0;
    	int edgecnt = 0;
    
    	for (int i = 0; edgecnt < V - 1; i++) {
    		int cost = edges[i].first;
    		int start = edges[i].second.first;
    		int end = edges[i].second.second;
    
    		if (!isCycle(start, end)) {
    			ans += cost;
    			updateParent(start, end);
    			edgecnt++;
    		}
    	}
    
    	cout << ans;
    }
    
    int main() {
    	ios::sync_with_stdio(0);
    	cin.tie(0); cout.tie(0);
    
    	cin >> V >> E;
    
    	// union find 위해 부모 초기화
    	for (int i = 0; i <= V; i++) parent[i] = i;
    
    	int start, end, cost;
    	for (int i = 0; i < E; i++) {
    		cin >> start >> end >> cost;
    		edges.push_back(make_pair(cost, make_pair(start, end)));
    	}
    
    	// cost 오름차순으로 정렬
    	sort(edges.begin(), edges.end());
    	
    	solve();
    
    	return 0;
    }

    '백준 > 최소 스패닝 트리' 카테고리의 다른 글

    [백준 1774] 우주신과의 교감  (0) 2025.10.20
    [백준 1368] 물대기  (1) 2025.08.10
    [백준 1647] 도시 분할 계획  (1) 2023.09.16
    [백준 9372] 상근이의 여행  (0) 2023.09.16