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

이 문제의 경우  최소 신장  트리 문제중 하나로 일단  최소 신장 트리를 만드는 알고리즘으로 크루스칼을 사용해서 풀었다
크루스칼 알고리즘 전전 게시물에 작성했다시피 경로의 Cost가 낮은 경로들 부터 연결을 하지만 서로의 root 가 다른 경로들 만 연결 하고 각자의 root들을 합쳐질때마다 업데이트 해주면 되는 문제 였다 

 

이 문제에서는 핵심적으로 4개의로직이 있다.

1. 부모를 찾는 로직

int findParent(int x) {
	if (parent[x] == x)
		return x;
	else return parent[x] = findParent(parent[x]);

이 로직은 x의 부모 root를찾는 코드로 재귀적으로 부모를 찾으면서 부모를 업데이트도 해주는 코드이다

 

2. 같은 부모인지 찾는 로직

bool sameParent(int x, int y) {
	x = findParent(x);
	y = findParent(y);
	if (x == y)
		return true;
	else
		return false;

 

3. 2개의 다른 트리를 합치는 로직 합칠때는 합쳐진 트리의 부모만 바꿔주면 된다

void uni(int  x, int y) {
	x = findParent(x);
	y = findParent(y);
	parent[y] = x;
}

 

4. cost가 낮은 순 부터 오름차순으로 입력 데이터를 정렬 한다 그후 루프를 돌면서  2번 3번 과정을 반복해준다 그후 연결된 cost중 가장  높은부분을 뺴준다 그 이유는 이문제에서 마을을 두개로 분리한다고 하였으니 가장 비용이 많이 드는 길 을 없애면 된다

	for (int i = 0; i < inputData.size(); i++) {
		if (!sameParent(inputData[i].second.first, inputData[i].second.second)) {
			uni(inputData[i].second.first, inputData[i].second.second);
			cost += inputData[i].first;
			cnt += 1;
			if (cnt == v - 1) {
				cost -= inputData[i].first;
			}
		}
	}

 

 

전체 코드는 아래와 같다

#include<iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 가중치 start end순
vector<pair<int, pair<int, int>>> inputData;
int parent[100001] = { 0, };

int findParent(int x) {
	if (parent[x] == x)
		return x;
	else return parent[x] = findParent(parent[x]);
}

bool sameParent(int x, int y) {
	x = findParent(x);
	y = findParent(y);
	if (x == y)
		return true;
	else
		return false;
}
void uni(int  x, int y) {
	x = findParent(x);
	y = findParent(y);
	parent[y] = x;
}
int main() {
	int  v, e;
	long long cost;
	cost = 0;
	int cnt = 0;
	cin >> v >> e;
	int tmp1, tmp2, tmp3;
	for (int i = 0; i < e; i++) {
		cin >> tmp1 >> tmp2 >> tmp3;
		inputData.push_back({ tmp3,{tmp1,tmp2} });
	}

	sort(inputData.begin(), inputData.end());
	for (int i = 1; i <= v; i++) {
		parent[i] = i;
	}

	for (int i = 0; i < inputData.size(); i++) {
		if (!sameParent(inputData[i].second.first, inputData[i].second.second)) {
			uni(inputData[i].second.first, inputData[i].second.second);
			cost += inputData[i].first;
			cnt += 1;
			if (cnt == v - 1) {
				cost -= inputData[i].first;
			}
		}
	}
	cout << cost;
}

'백준(코테준비) > 그래프' 카테고리의 다른 글

백준 2887 / C++ / 그래프 / 크루스  (0) 2025.01.12
백준 2252 / CPP / 위상 정렬  (1) 2024.12.01
백준 4386 / C++  (0) 2024.08.04
백준 1922  (0) 2024.07.27
백준 1197  (0) 2024.07.27

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

이 문제는 전형 적인 그리디 문제이다 그리디 문제의 특징은 모든 과정에서의 답이아니기 때문에 풀 수 있다

이문제는 일단 주의 할점을 일반적으로 input을 받으면 int 형자료형은 50만자리의 수를 받을 수없기 때문에 string으로 input을 받아 사용하는게 좋다

 

또한 이문제는 스택을 두고 이전에 들어온 값들보다 현재 들어오는 값들을 뽑고 거기에 넣으면서 뽑은 횟수를 저장해야한다 그래서 만약에 최대 뽑기수보다 못뽑으면 그냥 그상태로 값이 나온다

#include<iostream>
#include<stack>
#include<vector>
#include <algorithm>
using namespace std;
stack<long long> bigStack;
stack<long long> answerStack;
long long n, k;
string num;
vector<long long> arr;
long long popCount=0;
long long result = 0;
int main() {
	cin >> n >> k;
	cin >> num;
	for (int i = 0; i < num.length(); ++i) {
		arr.push_back(num[i] - '0');  // 문자 '0'을 빼서 실제 숫자로 변환
	}

	if(arr.size()!=0)
		bigStack.push(arr[0]);
	for (long long i = 1; i < n; i++) {
		while (!bigStack.empty()&& bigStack.top() < arr[i] && popCount<k) {
			bigStack.pop();
			popCount += 1;
		}
		bigStack.push(arr[i]);
	}
	while (popCount < k) {
		bigStack.pop();
		popCount += 1;
	}
	while (!bigStack.empty()) {
		answerStack.push(bigStack.top());
		bigStack.pop();
	}

	while (!answerStack.empty()) {
		cout << answerStack.top();
		answerStack.pop();
	}

}

'백준(코테준비) > 그리디' 카테고리의 다른 글

백준 1092 / CPP  (0) 2024.12.01
백준 12904  (0) 2024.08.09
백준 1744  (0) 2024.07.27
백준 1202  (0) 2024.07.27
백준 2437  (0) 2024.07.20

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

이 문제의 경우 bfs 문제이다 

우리가 구해야 할 답은 총 3개다
1 번과 2번은 그냥 우리가 아는 bfs 로 영역의 최대 크기와 영역의 갯수를 구해주면된다
3번은 내가 있는 방을 기준으로 4방의 방에서 벽을 뚫는다고 가정하고 풀었다 그후 모든 방에서 상하좌우방을 뚫었을 때 진행할수 있으면 진행 하도록 코드를 작성 하였다

#include <iostream>
#include<bitset>
#include <queue>
#include <cstring>
using namespace  std;
int arr[50][50];
bool isVisited[50][50];
int n, m;
int maxCnt = 1;
int xi[4] = { 0,1,0,-1 };
int yi[4] = { 1,0,-1,0 };
queue<pair<int, int>> bfsq;
bool canGo(int x, int y , int z) {
	if (x >= 0 && x < m && y >= 0 && y < n && !isVisited[x][y]) {
		if (arr[x][y] & (1 << z)) {
			return false;
		}
		else
			return true;
	}
	return false;
}
bool canGo(int x, int y) {
	if (x >= 0 && x < m && y >= 0 && y < n ) {
		return true;
	}
	return false;
}

void bfs(int startX, int startY) {
	bfsq.push({ startX,startY });
	isVisited[startX][startY] = true;
	int cnt = 1;
	while (!bfsq.empty()) {
		int col = bfsq.front().first;
		int row = bfsq.front().second;
		bfsq.pop();
		for (int i = 0; i < 4; i++) {
			if (canGo(col + xi[i], row + yi[i],i)) {
				bfsq.push({ col + xi[i] , row + yi[i] });
				isVisited[col + xi[i]][row + yi[i]] = 1;
				cnt += 1;
				if (maxCnt < cnt)
					maxCnt = cnt;
			}
		}
	}
}
int main() {
	int roomCnt=0;
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			cin >> arr[i][j];
		}
	}
	
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (isVisited[i][j])
				continue;
			roomCnt += 1;
			bfs(i, j);
		}
	}
	cout << roomCnt << endl;
	cout << maxCnt << endl;
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++){
			for (int k = 0; k < 4; k++) {
				if (canGo(i + xi[k], j + yi[k]) && (arr[i + xi[k]][j + yi[k]] &(1<<k))) {
					memset(isVisited, 0, sizeof(isVisited));
					arr[i + xi[k]][j + yi[k]] ^= (1 << k);
					bfs(i, j);
					arr[i + xi[k]][j + yi[k]] |= (1 << k);
				}
			}
		}
	}

	cout << maxCnt;
}

'백준(코테준비) > 비트마스킹' 카테고리의 다른 글

백준 2098 / C++ / dp + 비트마스킹 + dfs  (0) 2025.01.10
백준 19942 / CPP  (0) 2024.11.29
백준 15661  (0) 2024.07.25
백준 1052  (5) 2024.07.19

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

이 문제는 dp의 기본적인 문제이다 이문제의 경우 동전의 종류 와 만들 수 있는 동전의 크기가 있다.
이문제는 내가 현재 들고있는 동전을 추가해서 현재의 가치를 만들때 최소한의 동저만 쓴경우만 선택해서 진행한다
한번 표로 봐보자

우리가 가진 동전으로 0원을 만들수 있는 경우의 수는 0 이다 만들수 없다
1원은 현재 1원하나로 만들고 5원 12원으로 만들기 위해서는 -4원 -11원 이 있어야 만들 수 있는데 해당 원수는 없으니 제외한다

자 쭉쭉 진행 되었을 때를 보자

이 상태 에서 10원을 만든다고 가정해보자 9원에서 1원을 추가해서 만드는 방법하나와 5원에서 5원을 하나 추가하는 방법이 있다 이경우 5원에서 동전 하나를 추가해서 만드는게 동전 2개이므로 5원에서 현재 5원을 선택해서 +1 해주는 방식으로 2를 넣어준다 

이문제의 점화식은

arr[i]=min(arr[i], arr[i - coin[j]] + 1);
내가 현재 선택한 동전을 추가했을 때 나올수 있는 경우의 수중 최소를 선택해주면 된다 전체 코드는 아래와 같다

#include <iostream>
#include <algorithm>
using namespace std;
#define INF 987654321
int n, k;
int coin[100];
int arr[10000] = { 0, };
int main() {
	cin >> n >> k;
	for(int i=0;i<n; i++){
		cin >> coin[i];
	}
	for (int i = 1; i <= k; i++) {
		arr[i] = INF;
		for (int j = 0; j < n; j++) {
			if (i - coin[j] >= 0) {
				arr[i]=min(arr[i], arr[i - coin[j]] + 1);
			}
		}
	}
	if (arr[k]==INF)
		cout << -1;
	else
		cout << arr[k];
}

'백준(코테준비) > DP' 카테고리의 다른 글

백준 5972  (0) 2024.08.08
백준 11404/c++  (0) 2024.08.02
백준 14284  (1) 2024.07.25
백준 11054  (3) 2024.07.25
백준 9251  (0) 2024.07.17

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

이 문제는 내가 완전 감을 잘못 잡고 풀고 있었다. 이 문제를 증가수열 비슷하게 풀려고 했었다 하지만 이렇게 풀면 로직이 꼬였는데 테스트케이스 몇개는 잘나왔으나 몇개는 매우 잘 나오지 않았다.

이 문제의 로직은 현재 나를 기준으로 내왼쪽에서의 최대높이와 내오른 쪽의 최대높이를 비교해서 낮은 높이를 선택 해주는 문제 였다 단 오른쪽 과 왼쪽의 최대높이가 나보다는 클때만 빗물이 받아지니 해당 상황일때만 계산하도록 코드를 작성한다 그림으로 나타내면 대충 아래와 같다

해당 로직에 대한 코드는 아래 와 같다

#include <iostream>
#include<algorithm>
using namespace std;
int h, w;
int arr[500];
int main() {
	cin >> h >> w;
	int result = 0;
	for (int i = 0; i < w; i++) {
		cin >> arr[i];
	}
	for (int i = 1; i < w - 1; i++) {
		int lmax = 0;
		int rmax = 0;
		for (int j = 0; j < i; j++) {
			if (lmax < arr[j] && arr[j]>arr[i])
				lmax = arr[j];
		}
		for (int j = i + 1; j < w; j++) {
			if (rmax < arr[j] && arr[j]>arr[i])
				rmax = arr[j];
		}
		if (lmax != 0 && rmax != 0)
			result += min(lmax, rmax) - arr[i];
	}
	cout << result;

}

'백준(코테준비) > 증가수열&투포인터' 카테고리의 다른 글

백준 2473 / CPP / 투포인터  (0) 2025.01.15
프로그래머스 조이스틱 / C++ / 투포인터  (0) 2024.08.24
백준 2631 / C++  (0) 2024.08.09
백준 1644  (0) 2024.07.26
백준 2170  (0) 2024.07.19

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

이 문제의  경우 나는 일단 dfs와 ㅗ 모양의 블록을 나눠서 풀었다 .

테트로미노에는 이렇게 현재 블럭이 있는데

빨간색을 제외한 블록들은 dfs로 검색하면 회전까지 나오는 모양 들이다 빨간색으로 둘러싼 모형들을 배열에다 다 넣어서 최대값을 구하는게 해당 문젠데 그후 빨간색으로 둘러친걸 넣어보면서 최대값을 구하면 된다

 

일단 빨간색을 제외한 코드의 부분은

void dfs(int x, int y, int cnt , int sum) {
	if (cnt == 4) {
		if (sum > maxNum) {
			maxNum = sum;
		}
	}
	else {
		if (canGo(x + 1, y)) {
			isVisited[x + 1][y] = true;
			dfs(x + 1, y, cnt + 1, sum + arr[x+1][y]);
			isVisited[x + 1][y] = false;
		}
		if (canGo(x - 1, y)) {
			isVisited[x - 1][y] = true;
			dfs(x - 1, y, cnt + 1, sum + arr[x-1][y]);
			isVisited[x - 1][y] = false;
		}
		if (canGo(x , y+1)) {
			isVisited[x][y+1] = true;
			dfs(x , y+1, cnt + 1, sum + arr[x][y+1]);
			isVisited[x][y + 1] = false;
		}
		if (canGo(x , y-1)) {
			isVisited[x ][y-1] = true;
			dfs(x , y-1, cnt + 1, sum + arr[x][y-1]);
			isVisited[x][y - 1] = false;
		}
	}
}

이렇게 된다 그이이유는 저위에 빨간색을 제외한 부분들을 회전과 대칭을 고려할경우 dfs로 나오는 모형과 똑같기 떄문이다
그후 빨간색으로 둘러쳐진 모양은 노가다를 했다

void mountatinShape(int startX, int startY) {
	if (canGo(startX + 1, startY) && canGo(startX, startY - 1) && canGo(startX,startY + 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX + 1][startY] + arr[startX][startY - 1] + arr[startX][startY + 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}
	if (canGo(startX - 1, startY) && canGo(startX, startY - 1) && canGo(startX, startY + 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX - 1][startY] + arr[startX][startY - 1] + arr[startX][startY + 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}

	if (canGo(startX + 1, startY) && canGo(startX -1, startY) && canGo(startX, startY + 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX + 1][startY] + arr[startX-1][startY] + arr[startX][startY + 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}
	if (canGo(startX + 1, startY) && canGo(startX - 1, startY) && canGo(startX, startY - 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX + 1][startY] + arr[startX - 1][startY] + arr[startX][startY - 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}
}

그래서 이두 로직을 합치면서 최댓값을 저장해주면 이문제는 해결이다

#include<iostream>
using namespace std;
int n, m;
int arr[500][500];
bool isVisited[500][500] = { 0, };
int maxNum = 0;
//세로 1자
bool canGo(int px, int py) {
	if (px >= 0 && px < n && py >= 0 && py < m && !isVisited[px][py]) {
		return true;
	}
	else
		return false;
}
void dfs(int x, int y, int cnt , int sum) {
	if (cnt == 4) {
		if (sum > maxNum) {
			maxNum = sum;
		}
	}
	else {
		if (canGo(x + 1, y)) {
			isVisited[x + 1][y] = true;
			dfs(x + 1, y, cnt + 1, sum + arr[x+1][y]);
			isVisited[x + 1][y] = false;
		}
		if (canGo(x - 1, y)) {
			isVisited[x - 1][y] = true;
			dfs(x - 1, y, cnt + 1, sum + arr[x-1][y]);
			isVisited[x - 1][y] = false;
		}
		if (canGo(x , y+1)) {
			isVisited[x][y+1] = true;
			dfs(x , y+1, cnt + 1, sum + arr[x][y+1]);
			isVisited[x][y + 1] = false;
		}
		if (canGo(x , y-1)) {
			isVisited[x ][y-1] = true;
			dfs(x , y-1, cnt + 1, sum + arr[x][y-1]);
			isVisited[x][y - 1] = false;
		}
	}
}

void mountatinShape(int startX, int startY) {
	if (canGo(startX + 1, startY) && canGo(startX, startY - 1) && canGo(startX,startY + 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX + 1][startY] + arr[startX][startY - 1] + arr[startX][startY + 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}
	if (canGo(startX - 1, startY) && canGo(startX, startY - 1) && canGo(startX, startY + 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX - 1][startY] + arr[startX][startY - 1] + arr[startX][startY + 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}

	if (canGo(startX + 1, startY) && canGo(startX -1, startY) && canGo(startX, startY + 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX + 1][startY] + arr[startX-1][startY] + arr[startX][startY + 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}
	if (canGo(startX + 1, startY) && canGo(startX - 1, startY) && canGo(startX, startY - 1) && canGo(startX, startY)) {
		int sum = 0;
		sum = arr[startX + 1][startY] + arr[startX - 1][startY] + arr[startX][startY - 1] + arr[startX][startY];
		if (sum > maxNum)
			maxNum = sum;
	}
}
void tet1(int startX, int startY) {
	isVisited[startX][startY] = true;
	dfs(startX, startY, 1,arr[startX][startY]);
	isVisited[startX][startY] = false;

}

int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
		}
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			mountatinShape(i, j);
			tet1(i, j);
		}
	}

	cout << maxNum;
}

 

'백준(코테준비) > 브루트포스' 카테고리의 다른 글

백준 17135 / C++ / dfs / bfs / 브루트 포스  (0) 2025.01.12
백준 12100  (0) 2024.12.06
백준 2589 / CPP  (0) 2024.11.29
백준 1038  (0) 2024.11.26

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

이 문제는 솔직히 설명이 겁나 불친절하다 

정확히 이문제는 핵심이 나를 기준으로 나보다 크기가 작고 같은 거리에 있는 물고기 들은 위에에서 왼쪽부터 오른쪽 까지 검사하고 내려와서 왼쪽부터 오른쪽 까지 검사하면서 이 순으로 탐색을 하는 거였다.
단 위에를 듣고 BFS  이동방향을 1,0 ->0,-1 ->0,1 ->-1,0 이렇게 만 하면 안풀린다

while (!bfsQ.empty()) {
		
				otherX = bfsQ.front().second.first;
				otherY = bfsQ.front().second.second;
				otherCost = bfsQ.front().first;
				if (CanEat(otherX, otherY) && otherCost<=cost) {
					if (otherX < startX) {
						startX = otherX;
						startY = otherY;
						otherCost = cost;
					}
					else if (otherX == startX && startY>otherY ) {
						startX = otherX;
						startY = otherY;
						otherCost = cost;
					}
				}

핵심은 이부분이다 내가 물고기를 먹을 수있는 지역으로 갔을 때 현재 큐에  들어와 있는 것중 나보다 거리가 작거나 같고 행의 값이  위에 있거나 혹은 행이 같다면 열값이 더 먼저인 애를 찾아서 거기를 가야한다 이에 의해 필자는 행을 검사에서 위에있으면 해당 행으로 탐색지점을 바꿔줬고 같다면 열값이 더 작은 쪽으로 옮겨줬다

#include <iostream>
#include <queue>
using namespace std;
int n;
int arr[20][20] = { 0, };
bool isVisited[20][20];
int fishSize = 2;
int eatFish = 0;
int cnt = 0;
queue<pair<int,pair<int, int>>>  bfsQ;

bool CanEat(int x, int y) {
	if (arr[x][y]>0&&arr[x][y] < fishSize) {
		return true;
	}
	return false;
}
bool canGo(int x, int y) {
	if (x >= 0 && x < n && y >= 0 && y < n && !isVisited[x][y] && (CanEat(x, y) || arr[x][y] == 0 || arr[x][y]==fishSize))
		return true;
	else
		return false;
}

void Bfs(int x, int y) {
	bfsQ.push({ cnt,{x,y} });
	arr[x][y] = 0;
	int startX, startY, cost;
	int otherX, otherY, otherCost;
	while (!bfsQ.empty()) {
		startX = bfsQ.front().second.first;
		startY = bfsQ.front().second.second;
		cost = bfsQ.front().first;
		bfsQ.pop();
		if (CanEat(startX, startY)) {
			cnt += cost;
			while (!bfsQ.empty()) {
		
				otherX = bfsQ.front().second.first;
				otherY = bfsQ.front().second.second;
				otherCost = bfsQ.front().first;
				if (CanEat(otherX, otherY) && otherCost<=cost) {
					if (otherX < startX) {
						startX = otherX;
						startY = otherY;
						otherCost = cost;
					}
					else if (otherX == startX && startY>otherY ) {
						startX = otherX;
						startY = otherY;
						otherCost = cost;
					}
				}

				bfsQ.pop();
				
			}
			bfsQ.push({ 0, {startX, startY}});
			eatFish += 1;
			if (eatFish == fishSize) {
				fishSize += 1;
				eatFish = 0;
			}
			arr[startX][startY] = 0;
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					isVisited[i][j] = false;
				}
			}
			isVisited[startX][startY] = true;
			cost = 0;
		}

		if (canGo(startX-1,startY)) {
			bfsQ.push({ cost + 1,{startX -1,startY}});
			isVisited[startX - 1][startY] = 1;
		}
		if (canGo(startX, startY-1)) {
			bfsQ.push({ cost + 1,{startX ,startY - 1} });
			isVisited[startX][startY-1] = 1;
		}
		if (canGo(startX , startY+1)) {
			bfsQ.push({ cost + 1,{startX ,startY + 1} });
			isVisited[startX][startY + 1] = 1;
		}
		if (canGo(startX+1 , startY)) {
			bfsQ.push({ cost + 1,{startX + 1,startY} });
			isVisited[startX + 1][startY] = 1;
		}
	}

}
int main() {
	cin >> n;
	int startIdxCol, startIdxRow;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 9) {
				startIdxCol = i;
				startIdxRow = j;
			}
		}
	}

	Bfs(startIdxCol, startIdxRow);
	cout << cnt;
}

'백준(코테준비) > DFS,BFS' 카테고리의 다른 글

백준 16234 / C++  (0) 2024.08.17
백준 1520 / C++  (0) 2024.08.07
백준 9019  (0) 2024.07.16
백준 1987  (0) 2024.07.16
프로그래머스 PCCP 기출 2  (2) 2024.01.03

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

이번 문제도 그래프를 이용해 최소 신장 트리를 만드는 문제이다 단 저번 게시물에는 크루스칼 알고리즘을 이용 하였으나 이번 알고리즘은 프림 알고리즘을 이용해서 풀었다.

 

프림 알고리즘은 현재 나와 연결된 노드들을 점점확장하면서 최소 신장 트리를 만드는 것이다
프림 알고리즘은 크루스칼알고리즘과 다르게 간선들이 많을 때 효율적이다.

프림알고리즘의 로직은 대충 일단 내가 갈수 있는 곳중 가까운 곳을 연결한다. 그리고 내가 갈수 있는 곳과 그 갈수 있는 버텍스를 통해서 갈수 있는 곳중 가장 비용이 낮은 곳으로 간다

위의 과정을 vertex의 갯수-1 만큼 반복해주면 된다.

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
int parent[1001];
vector<priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>>> inputData(1001);
int findParent(int x) {
	if (parent[x] == x)
		return x;
	else return parent[x] = findParent(parent[x]);
}
bool isSameParent(int x, int y) {
	int parentOfX = findParent(x);
	int parentOfY = findParent(y);
	if (parentOfX == parentOfY) {
		return true;
	}
	else {
		return false;
	}
}

void uni(int x, int y) {
	x = findParent(x);
	y = findParent(y);
	parent[y] = x;
}
int main() {
	int n, m;
	cin >> n;
	cin >> m;
	int com1 = 0, com2 = 0, cost = 0,result=0;
	for (int i = 0; i < m; i++) {
		int from, to, cost;
		cin >> from >> to >> cost;
		inputData[from].push({ cost,to });
		inputData[to].push({ cost,from });
	}
	for (int i = 1; i <= n; i++) {
		parent[i] = i;
	}
	for (int i = 1; i < n ; i++) {
		while (!inputData[1].empty()) {
			com1 = 1;
			com2 = inputData[1].top().second;
			cost = inputData[1].top().first;
			inputData[1].pop();
			if (!isSameParent(com1, com2)) {
				result += cost;
				uni(com1, com2);
				while (!inputData[com2].empty()) {
					inputData[com1].push(inputData[com2].top());
					inputData[com2].pop();
				}
				break;
			}
		}
	}
	cout << result;
}

'백준(코테준비) > 그래프' 카테고리의 다른 글

백준 2887 / C++ / 그래프 / 크루스  (0) 2025.01.12
백준 2252 / CPP / 위상 정렬  (1) 2024.12.01
백준 4386 / C++  (0) 2024.08.04
백준 1647 / C++  (0) 2024.08.04
백준 1197  (0) 2024.07.27

+ Recent posts