문제 출처: https://www.acmicpc.net/problem/14503


풀이

최초의 로봇청소기의 좌표로부터 4방향을 검색하면서 방향을 바꾸는 연산이 너무 까다로웠습니다..

로봇 청소기의 좌표 및, 방향을 담을 수 있는 큐를 선언하여 bfs를 이용했습니다. 

현재 자리에서 왼쪽부터 탐색하여 벽이있거나, 이미 청소했을 경우, 방향을 그 쪽으로 돌리는게 핵심이었습니다. 

문제에서 주어진대로 0번 인덱스:북, 1번: 동, 2번 : 남, 3번 서 쪽으로 각각 지정해서 dx[4],dy[4] 좌표를 선언했습니다. 


bfs 수행중에 중요한것은, 네 방향을 방향 순서에 따라 탐색 중, 청소할 수 있는 좌표를 만나면 좌표를 남기고 탈출해야합니다.(4번연산하지않게)


왼쪽부터 탐색하여 향하는 방향을 갱신해주는 연산 코드는 아래와 같습니다. (이게 너무 어려웠습니다.) 매번 향하는 순서가 규칙적이므로, 아래 코드가 성립합니다.


int next_go = (go + (3 - i)) % 4;


그리고 두번 쨰로 까다로운 연산은 후진 할 떄, 방향은 유지하며 후진하는 것입니다. 그런데 사실 까다로운건 없습니다. 아래와 같이 작성하면 이게 곧 그 뜻이됩니다.


int by = y - dy[go];

int bx = x - dx[go];


이렇게 식을 세울줄 알면 끝이라서,, 나머지설명은 주석으로 확인해주세요.


코드

#include<iostream> #include<queue> using namespace std; int map[50][50]; int dy[4] = { -1,0,1,0 }; int dx[4] = { 0,1,0,-1 }; int n, m, r, c, d, room; queue<pair<pair<int, int>,int>> q; void bfs(); int main() { cin >> n >> m >> r >> c >> d; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) cin >> map[i][j]; bfs(); cout << room; } void bfs() { q.push({ {r,c},d }); while (!q.empty()) { int y = q.front().first.first; int x = q.front().first.second; int go = q.front().second; if (map[y][x] == 0) { room++; map[y][x] = 10; } q.pop(); bool check = false; for (int i = 0; i < 4; i++) { //좌표의변화. 이게 너무어려웠음 int next_go = (go + (3 - i)) % 4; int ny = y + dy[next_go]; int nx = x + dx[next_go]; //(1,0)인상태) if (nx >= 0 && ny >= 0 && nx < m && ny < n) { if (map[ny][nx] == 0) { q.push({ {ny,nx},next_go }); check = true; break; } } } //네 방향 모두 청소되어있을떄 || 네방향모두 벽일 때 if (!check) { //방향을 유지하며 한칸 후진. int by = y - dy[go]; int bx = x - dx[go]; //후진할 수 있으면 후진해서 다시 시작 if ((0 <= by && by < n && 0 <= bx && bx < m) && map[by][bx] != 1) q.push({ {by, bx}, go }); //후진할 수 없으면 종료 else break; } //빈칸을 찾아서 청소하러 이동한경우 skip else continue; } }


결과

'문제풀이(BOJ) > 삼성 sw역량테스트 기출' 카테고리의 다른 글

[백준 17144] 미세먼지 안녕!  (0) 2020.01.29
[백준 3190] 뱀  (0) 2020.01.29
[백준 14501] 퇴사  (0) 2020.01.27
[백준 14499] 주사위 굴리기  (0) 2020.01.27
[백준 13458] 시험 감독  (0) 2020.01.27

문제 출처: https://www.acmicpc.net/problem/14501


풀이

재귀함수 사용을 많이 어려워하는데, 아이디어는 알겠는데 구현력이부족해서 다른분들의 코드를 참고했습니다.

재귀함수를 사용하여 모든 케이스를 탐색해보는 방법을 사용했습니다.

나올수있는 경우는 1. 오늘 상담하고, 상담한 날만큼 건너뛰기 2. 상담안하고 하루 건너뛰기가 있습니다. 이것을 재귀로 구현해주면됩니다.

모든경우를 탐색하므로, 하루 건너뛰기를 수행하는 함수는 사실상 하루 이상의 day들을 건너뛴다고 할 수 있습니다.(이걸몰라서....)


코드

#include<iostream>
#include<algorithm>
using namespace std;
int t[16];
int p[16];
int n, max_val;
void func(int day,int profit);
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> t[i] >> p[i];
	//day=1일,이익0으로시작
	func(1, 0);
	cout << max_val << endl;
}
void func(int day,int profit)
{
	//탈출조건
	if (day > n + 1)return;
	//day==n+1이면max값 갱신후 종료(답)
	if(day==n+1)
	{
		max_val = max(max_val, profit);
		return;
	}
	//두가지 case

	//1. 오늘 상담하고,상담한 날만큼 건너뛰기
	if (day + t[day] <= n + 1)
	//두번째인자의, +p[day]해주는이유는 profit이 누적이고, p[day]가 그 날의 이익이므로
		func(day + t[day], profit+p[day]);
	//상담안하고 넘어간다.
	if (day + 1 <= n + 1)func(day + 1, profit);
}


결과

'문제풀이(BOJ) > 삼성 sw역량테스트 기출' 카테고리의 다른 글

[백준 17144] 미세먼지 안녕!  (0) 2020.01.29
[백준 3190] 뱀  (0) 2020.01.29
[백준 14503] 로봇 청소기  (0) 2020.01.28
[백준 14499] 주사위 굴리기  (0) 2020.01.27
[백준 13458] 시험 감독  (0) 2020.01.27

문제 출처: https://www.acmicpc.net/problem/14499


풀이

푸는데 2시간넘게걸린 문제입니다. 주사위가 돌아갈 때를 머릿속으로 그릴줄 알고 어느정도 공간감각력이 필요한 것 같습니다.

이 문제의 핵심은 주사위를 굴릴 때, 변화하는 주사위의 위치를 본인이 기준을 세워서 그 기준안에서 돌아가게끔 해야하는것입니다.

저는 문제에서 보기로 주어진 평면도를 기준으로삼았습니다.

즉, 보기의 평면도를 주사위로접으면, 아래 그림처럼 됩니다. 이 기준을 삼아서 최종적으로 dice[6](윗면)가 답으로 출력되게끔했습니다.


위의 평면도 상에서, 주사위를 동,서,남,북 방향으로 돌려보면, 규칙이 보입니다.(규칙이라기보단 당연한 내용입니다.)

동쪽, 서쪽 으로 돌리면, 2,5번 면은 움직이지 않고, 북쪽,남쪽으로 돌리면 3,4번 면은 움직이지않습니다.

이렇듯, 한번 돌리고 나서 변화하는 위치를 기억하기 위해 주사위의 복사본으로 변화하는 좌표를 담고, 기존 주사위를 변화할 수 있게 합니다.

이처럼, 본인이 삼은 위치의 변화의 기준을 이용하여 문제에 맞게 코드를 작성하면됩니다.


주의사항

이 부분 때문에 오래걸렸는데, 문제에서 지도의 좌표(r,c)는, 입력받을 (y,x)와 동일하기 때문에, x,y순이 아닌 y,x순으로 입력을 해야합니다.

(이걸로 틀리게하는건 좀 유치하다고생각하는데...)


코드

#include<iostream>
using namespace std;
int dice[7];
int temp[7];

int map[21][21];
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	int n, m, y, x, k, call;
	cin >> n >> m >> y >> x >> k;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			cin >> map[i][j];
	
	for (int i = 0; i < k; i++)
	{
		cin >> call;
		if (call == 1)
		{
			if (x+1<m)
			{
				x = x + 1;
				temp[4] = dice[4];
				temp[1] = dice[1];
				temp[3] = dice[3];
				temp[6] = dice[6];


				dice[4] = temp[1];
				dice[1] = temp[3];
				dice[3] = temp[6];
				dice[6] = temp[4];
				if (map[y][x ] == 0)
				{
					map[y][x ] = dice[1];
				}
				else
				{
					dice[1] = map[y][x ];
					map[y][x ] = 0;
				}
				cout << dice[6] << endl;
			}
		}
		else if (call == 2)
		{
			if (x - 1 >= 0)
			{
				x = x - 1;
				temp[4] = dice[4];
				temp[1] = dice[1];
				temp[3] = dice[3];
				temp[6] = dice[6];


				dice[4] = temp[6];
				dice[1] = temp[4];
				dice[3] = temp[1];
				dice[6] = temp[3];
				if (map[y][x ] == 0)
				{
					map[y][x ] = dice[1];
				}
				else
				{
					dice[1] = map[y][x ];
					map[y][x ] = 0;
				}
				cout << dice[6] << endl;
			}		
		}
		else if (call == 3)
		{
			if (y - 1 >= 0)
			{
				y = y - 1;
				temp[2] = dice[2];
				temp[1] = dice[1];
				temp[5] = dice[5];
				temp[6] = dice[6];

				dice[2] = temp[6];
				dice[1] = temp[2];
				dice[5] = temp[1];
				dice[6] = temp[5];

					if (map[y][x] == 0)
					{
						map[y][x] = dice[1];
					}
					else
					{
						dice[1] = map[y][x ];
						map[y][x ] = 0;
					}
				cout << dice[6] << endl;
			}
		}
		else if (call == 4)
		{
			if (y + 1 <n)
			{
				y = y + 1;
				temp[2] = dice[2];
				temp[1] = dice[1];
				temp[5] = dice[5];
				temp[6] = dice[6];

				dice[2] = temp[1];
				dice[1] = temp[5];
				dice[5] = temp[6];
				dice[6] = temp[2];
				if (map[y][x] == 0)
				{
					map[y ][x] = dice[1];
				}
				else
				{
					dice[1] = map[y][x];
					map[y ][x] = 0;
				}
				cout << dice[6] << '\n';
			}
		}
	}
}


결과







'문제풀이(BOJ) > 삼성 sw역량테스트 기출' 카테고리의 다른 글

[백준 17144] 미세먼지 안녕!  (0) 2020.01.29
[백준 3190] 뱀  (0) 2020.01.29
[백준 14503] 로봇 청소기  (0) 2020.01.28
[백준 14501] 퇴사  (0) 2020.01.27
[백준 13458] 시험 감독  (0) 2020.01.27

문제 출처: https://www.acmicpc.net/problem/13458


풀이 

각 시험장에 총 감독관은 1명만 있어야하므로, 정답을 구할 때는 총감독관1명을 배치하고 남는 인원들에 대해서 부감독관을 구하는게 제일 빠릅니다. 

그렇기 때문에 그리디 알고리즘문제라고 할 수 있겠습니다.

길게  풀이를 적어내면 이해가 더 안갈 것같아 최대한 간략하게 풀이순서대로 작성해봤습니다.


1. ans는 int형이 아닌 longlong형으로 선언해야한다.

b,c가 1이고 각 시험장에 1,000,000씩 있으면 int형으로 표현불가


2. 총감독관부터 배치한다.

num[i]>=b, num[i]==b, num[i]<b일때 3가지 경우에 대해서 일단 연산해야함(그리디)

이 때, num[i]<b라면, 정답은 1이므로, 맨마지막 else문에 적어두고 위의 연산들만 신경쓰자. 


3. 총감독관을 구하고, 남은 인원들에 대해 부감독관을 구한다.

num[i]>=b, num[i]==b일 때 b를 구하고, 그 식 안에 c에 대해 똑같이 경우를 나누어서 구하자.



주의 사항

1. 조건 속 "b,c에 대해 (b>=1,c>=1)", "C는 여러명이 있을 수 있다." 를 C도 최소 한명있어야 한다로 해석하면안됨.


즉, 

인원 : 10

B: 10 , C: 10 일 때

B 1명, C 1명 이라고 해석하면 안됨. 테스트케이스 1번 결과를 참고해야한다. 


2. if문안에각 연산이 끝나고 다른 식을 실행하지않게 적절히 if문을 사용해야함. 이것만 주의하면 끝끝끝


코드

#include<iostream>
using namespace std;
int num[1000001];
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	int n, b, c; 
	//long long 해야함
	long long ans = 0;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> num[i];
	cin >> b >> c;
	for (int i = 1; i <= n; i++)
	{
		//num[i]가 b가관리할수있는인원보다많으면
		if (num[i] >=b)
		{
			//ex)10 10이면 
			if (num[i] == b)
			{
				//c가 최소 1이므로
				ans += 1;
			}
			//num[i]>b일 때
			else
			{
				//일단 총감독관은 무조건++해주고,
				ans++;
				//남는 인원에 대해서 부감독관구함
				num[i] -= b;
				
				//c에대해 연산
				if (num[i] <= c)
				{
					ans++;
					
				}
				//num[i]>c
				else
				{
					//짝수처리
					if (num[i] % c == 0)
					{
						ans += num[i] / c;
						
					}
					//홀수처리
					else
					{
						ans += num[i] / c + 1;
						
					}
				}
				
			}
		}
		//num[i]<b일때
		else
		{
			//총감독관한명만 배치하면됨.
		//주의!!: C도 한명추가되는게아님!!
			ans += 1;
		}
	}
	cout << ans << '\n';
}


결과

'문제풀이(BOJ) > 삼성 sw역량테스트 기출' 카테고리의 다른 글

[백준 17144] 미세먼지 안녕!  (0) 2020.01.29
[백준 3190] 뱀  (0) 2020.01.29
[백준 14503] 로봇 청소기  (0) 2020.01.28
[백준 14501] 퇴사  (0) 2020.01.27
[백준 14499] 주사위 굴리기  (0) 2020.01.27

문제출처: https://www.acmicpc.net/problem/2458


풀이

https://www.acmicpc.net/problem/10159 와 거의 동일한 플로이드와샬 알고리즘문제입니다 !


키를 비교할 수 있는 학생의 수는 그 학생보다 키가 작거나 키가 크거나, 이 둘중 하나는 무조건 해당되야합니다.

즉, 비교하고자 하는 학생(X)은 X를 거치는 학생과 X에서 뻗어나가는 학생의 수가 총원이되어야합니다. 

X가 모든학생이 연결되어있어야 한다는것입니다.


X와 연관이없는(x와 이어지는 노드가 없는 경우) 학생이 한명이라도 있다면, 문제의 조건을 어긋나게됩니다.!


코드

#include<iostream>
using namespace std;
int map[501][501];
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	int n, m, a, b;
	cin >> n >> m;
	for (int i = 0; i < m; i++)
	{
		cin >> a >> b;
		map[a][b] = 1;
	}
	for (int k = 1; k <= n; k++)
	{
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				if (map[i][k] && map[k][j])
					map[i][j] = 1;
			}
		}
	}
	int ans = 0;
	for (int i = 1; i <= n; i++)
	{
		int cnt = 0;
		for (int j = 1; j <= n; j++)
		{
			//본인은 제외하기
			if (i == j)continue;
			//학생->X &&X->학생 루트가 하나라도 없다면
			if (map[i][j] == 0 && map[j][i] == 0)
				//체킹
				cnt++;
		}
		//cnt=0 ? 모두연결되었다 
		//cnt>1 ? 연결되지않은 노드가있다.
		if (cnt == 0)ans++;
	}
	cout << ans<<'\n';
}


결과

'문제풀이(BOJ) > 플로이드와샬' 카테고리의 다른 글

[백준 1956] 운동  (0) 2020.02.11
[백준 1389] 케빈 베이컨의 6단계 법칙  (0) 2020.02.05
[백준 10159] 저울  (0) 2020.01.24
[백준 11403] 경로 찾기  (0) 2020.01.15

문제출처: https://www.acmicpc.net/problem/10159


풀이

대충 그래프 문제이니, 예제를 그래프로그려봅니다. 그리고 보기의 답을 보면, x와 비교할 수없는 물건의 갯수는 x에서 다른 노드로 가는길과 다른 노드에서 x로 가는 길이 없을 때만 해당합니다. 결국, 플로이드와샬로 해결됨을 알 수 있습니다. 


부끄러운 얘기지만, 플로이드 코드를 작성해놓고 카운팅을하는 반복문작성에 시간을 많이 잡아먹었습니다. 헷갈리더라구요. 

플로이드알고리즘이 코드도 직관적이고 이해도 쉬운만큼, 그냥 눈으로만 보고 넘어갈 때가 있었는데 이번에 많이 반성했습니다. 

배운 개념은 꼭 복습을 하는 습관을 가집시다..


코드

#include<iostream>
using namespace std;
int map[101][101];
int main()
{
	int n, m, a, b;
	cin >> n >> m;
	for (int i = 0; i < m; i++)
	{
		cin >> a >> b;
		map[a][b] = 1;
	}
	//플로이드 돌려준다.
	for (int k = 1; k <= n; k++)
	{
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				if (map[i][k] && map[k][j])map[i][j] = 1;
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		int cnt = 0;
		for (int j = 1; j <= n; j++) {
			if (i == j)continue;
			//i에서 j로 가는길도없고, j에서 i로 가는길도 없을때 ++
			if (map[i][j] == 0 && map[j][i] == 0)cnt++;
		}
		cout << cnt << endl;
	}
}


결과

'문제풀이(BOJ) > 플로이드와샬' 카테고리의 다른 글

[백준 1956] 운동  (0) 2020.02.11
[백준 1389] 케빈 베이컨의 6단계 법칙  (0) 2020.02.05
[백준 2458] 키 순서  (1) 2020.01.24
[백준 11403] 경로 찾기  (0) 2020.01.15

문제출처: https://www.acmicpc.net/problem/1719


풀이

기존의 다익스트라함수에 경로를 추적할수있는 배열을 추가하여 연산해야합니다.

일단 각 노드에서 경로를 추적할 수 있게 정점의 갯수만한 1차원배열을 선언합니다.

그리고 다익스트라를 수행중에  최단거리를 수정하는 연산과정에서  경로를 추적할 수 있게  다음과같이 1줄만 작성해주면됩니다.

trace[next]=current의 의미는 current노드에서 next노드까지의 경로가 있음을 의미하고, 구체적으로는 

최단거리중 next노드 바로전의 경로가(거치는 길이)current노드임을 의미합니다.


예를들어, 2번노드에서 다익스트라를 돌려서 아래와 같이 구해진 최단경로를 봅시다.


이렇게 최단거리가 구성되는데, 문제에서 주어진 경로표를 보면 2번노드에서의 최단거리중 n번노드로 갈 때 가장 먼저 거치는 노드의번호와 같음을 알 수 있습니다.(당연한건데 그림을 그려야 보임)


최단 거리를 수정하는 if문 안에 경로추적배열을 선언하고, 출력할 때, 

1. 시작노드랑 x번노드랑 같을 때(본인이므로 "-" 출력)

2. trace[index]=x일때 (index노드전에 x노드가 붙어있으므로, index출력

3. trace[index]=x가 아닐때 (식이 성립할 때 까지 경로를 거슬러 올라가서 index출력)

이 3가지만 고려해서 코드작성하시면됩니다.



코드

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int INF = 200000;
vector<pair<int, int>>a[201];
int d[201];
int trace[201];
int n, m, u, v, w;
void dijsktra(int x);
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	cin >> n >> m;
	for (int i = 0; i <m; i++)
	{
		cin >> u >> v >> w;
		a[u].push_back({ v, w });
		a[v].push_back({ u, w });
	}
	for (int i = 1; i <= n; i++)
		dijsktra(i);
}
void dijsktra(int x)
{
	for (int i = 1; i <= n; i++)
		d[i] = INF;
	d[x] = 0;
	priority_queue<pair<int, int>>pq;
	pq.push({ 0,x });
	while (!pq.empty())
	{
		int current = pq.top().second;
		int distance = -pq.top().first;
		pq.pop();
		if (d[current] < distance)continue;
		for (int i = 0; i < a[current].size(); i++)
		{
			int next = a[current][i].first;
			int next_dis = distance + a[current][i].second;
			//최단거리를 갱신할 때 
			if (d[next] > next_dis)
			{
				//갱신된 거리의 경로를 담음
				trace[next] = current;
				d[next] = next_dis;
				pq.push(make_pair(-next_dis, next));
			}
		}
	}
	//1번노드에서 다익스트라 끝났을때, 1에서 출발하는 각 노드까지의 최단경로그림그려보면
	//trace[index]=dis일때, dis에서 index로 가는길이있음.
	//이 성질을 이용해서 트랙출력
	for (int i = 1; i <= n; i++) {
		if (i == x)
			cout << "- ";
		else if (trace[i] == x)
			cout << i<<" ";
		else
		{
			//x노드에서 가장 가까운 거치는 노드탐색
			//trace[index]=x일때가 x에서 index로 가는길이있으면서 x노드바로 전 노드가index노드일때이므로
			//위조건을 만족하는 index가 가장먼져 거치는 수,
			int index = i;
			while (1)
			{
				if (trace[index] == x)
				{
					cout << index<<" ";
					break;
				}
				//아닐 시에 최단거리의 경로를 거슬러 올라가본다.
				else
					index = trace[index];
			}
		}
	}
	cout << '\n';
}


결과

'문제풀이(BOJ) > 다익스트라' 카테고리의 다른 글

[백준 1238] 파티  (0) 2020.01.24
[백준 1916] 최소비용 구하기  (0) 2020.01.23
[백준 1753] 최단경로  (0) 2020.01.22

문제출처: https://www.acmicpc.net/problem/1238


풀이

출발->거쳐서->도착 의 패턴이 보여서 플로이드와샬 알고리즘이 끌리는데, 정점의 최대 갯수가 최대 1000이므로, 시간초과가 날 수 있습니다.

(그런데 684ms정도로 통과가 되긴하더라구요...아무튼 비추)


그래서 다익스트라를 쓰려는데, 다익스트라는 한 노드에서 다른 모든 노드로 가는 최단거리, 즉 ONE to ALL 알고리즘인데, 어떻게 적용해야할까요?


일반적인 생각은, X(목적지)에서 각 노드로 뻗어가는 최단거리와, 각각의 모든 노드에서 출발하는 최단거리들을 구한다음, 그 두 최단거리집합중

x에서 i노드로 가는 최단거리+ i에서 x로 가는 최단거리 중 가장 큰값이 답이 되겠죠.


그런데, 모든노드에서 다익스트라를 수행하므로 최대 1000*O(ElogV)= 1000* 10000*10= 약 1억므로 fail이 뜰 수도있습니다.

제출 시 거의 0ms로 통과될 수 있는 방법이있습니다. 조금만 생각해보면 매우 당연하고 간단합니다.


u,v,w를 입력받을 떄, 정점 u에서 v로 가는 가중치w만 연결시켜줄 뿐만 아니라, 역으로 v에서 u로가는 w로 가는 간선의 정보도 저장을해주면됩니다.

(역방향도 저장을 해준다는게, 방향그래프를 무방향그래프처럼 보겠다는겁니다. 단, 차이는 다익스트라를 두번의 경우로 나누어 돌려야하므로, 하나의 간선정보의 배열이 아닌 2개의 배열에 저장해야합니다.)


아래 그림을 보시면 이해가 갈겁니다.




원래의 그래프





역방향 그래프





보이시나요? 결국 각각의 그래프에서 목적지( 2번노드)부터 다익스트라를 돌린다음 각 노드로 가는 최단거리들을  합한값중 가장 큰값이 정답입니다.

즉, 시작->X+ X->도착 하는 값중 가장 큰 값을 구하는 것이므로, 문제의 조건그대로를 코드로 옮긴것입니다. 나머지는 코드를 보면서 이해하셨으면좋겠습니다.


코드 

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int INF = 100000;
//정방향,역방향의 간선정보담을 두개의 벡터선언
vector<pair<int, int>>a1[1001];
vector<pair<int, int>>a2[1001];
int d[1001];
//파티장소(x)에서의 정방향+역방향에서의 다익스트라값의 합 저장
int ans[1001];
int n, m, x, u, v, w;
void dijkstra(int start, vector<pair<int, int>>arr[1001]);
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	cin >> n >> m >> x;
	for (int i = 0; i < m; i++)
	{
		cin >> u >> v >> w;
		//x에서 정방향 다익스트라
		a1[u].push_back({ v,w });
		//x에서 역방향 다익스트라
		a2[v].push_back({ u,w });
		//결국 그림을그려보면, a1,a2에서의 x노드의 다익스트라 최단거리값의 합 중 가장큰값이 정답 
	}
	dijkstra(x, a1);
	dijkstra(x, a2);
	int max = 0;
	//저장된 값중에 가장 큰값이 정답(최단거리)
	for (int i = 1; i <= n; i++)
	{
		if (max < ans[i])
			max = ans[i];
	}
	cout << max << '\n';
}
void dijkstra(int start, vector<pair<int, int>>arr[1001])
{
	//각 최단거리를 INF로 초기화
	for (int i = 1; i <= n; i++)
		d[i] = INF;
	d[start] = 0;
	priority_queue<pair<int, int>>pq;
	pq.push({ 0,start });
	while (!pq.empty())
	{
		int current = pq.top().second;
		int distance = -pq.top().first;
		pq.pop();
		if (d[current] < distance)
			continue;
		for (int i = 0; i < arr[current].size(); i++)
		{
			int next = arr[current][i].first;
			int next_distance = arr[current][i].second + distance;
			if (d[next] > next_distance)
			{
				d[next] = next_distance;
				pq.push(make_pair(-next_distance, next));
			}
		}
	}
	//더해서 저장시킴 (정방향+역방향 총 2번 삽입하여 더해진값저장)
	for (int i = 1; i <= n; i++)
		ans[i] += d[i];
}


결과



 

'문제풀이(BOJ) > 다익스트라' 카테고리의 다른 글

[백준 1719] 택배  (0) 2020.01.24
[백준 1916] 최소비용 구하기  (0) 2020.01.23
[백준 1753] 최단경로  (0) 2020.01.22

+ Recent posts