https://www.acmicpc.net/problem/17270
지헌과 성하의 출발지로부터 새로운 약속 장소를 선정:약속 장소 후보는 지헌(J)과 성하(S)의 출발지가 아닌 위치여야 한다.약속 장소까지의 **최단 거리 합(지헌 → 약속 장소 + 성하 → 약속 장소)**이 최소인 위치를 선택한다.최단 거리 합이 같다면:지헌이 성하보다 늦게 도착하면 안 된다.지헌과 성하가 동시에 도착하거나, 지헌이 더 빨리 도착해야 한다.최종 조건을 만족하는 장소가 여러 개라면:지헌으로부터 가장 가까운 곳을 선택.그것도 같다면, 번호가 가장 작은 장소를 선택.
입력
첫 줄: 약속 장소 후보의 수 VVV와 길의 수 MMM.2≤V≤1002 \leq V \leq 1002≤V≤100, 1≤M≤1,0001 \leq M \leq 1,0001≤M≤1,000.다음 MMM개의 줄: a,b,ca, b, ca,b,c가 주어짐:aaa와 bbb는 길의 양 끝, ccc는 이동 시간.길은 양방향.마지막 줄: 지헌의 위치 JJJ, 성하의 위치 SSS.
출력
조건을 만족하는 최적 약속 장소를 출력.조건을 만족하는 장소가 없다면 **-1**을 출력.
void Dijstra(int st) {
reset_distance(); // 거리 배열 초기화
Distance[st] = 0; // 출발지까지의 거리는 0
q.push({-Distance[st], st}); // 우선순위 큐에 초기값 삽입
while (!q.empty()) {
int x = q.top().S; // 현재 노드
int cost = -q.top().F; // 현재 노드까지의 거리
q.pop();
if (Distance[x] < cost) continue; // 이미 더 짧은 거리가 있으면 스킵
// 현재 노드의 모든 인접 노드 탐색
for (int i = 0; i < connect[x].size(); i++) {
int xx = connect[x][i].F; // 다음 노드
int n_cost = cost + connect[x][i].S; // 다음 노드까지의 거리
// 더 짧은 거리를 발견하면 업데이트
if (Distance[xx] > n_cost) {
Distance[xx] = n_cost;
q.push({-Distance[xx], xx}); // 우선순위 큐에 삽입
}
}
}
}
if (i == J || i == S) continue;
JS_distance = min(JS_distance, J_Distance[i] + S_Distance[i]);
if (J_Distance[i] > S_Distance[i]) continue;
if (J_dis >= J_Distance[i]) {
J_dis = J_Distance[i];
Point = i;
}
#define _CRT_SECURE_NO_WARNINGS
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#define INF 2100000000 // 무한대를 나타내는 값
#define F first // pair에서 first를 F로 줄여 사용
#define S second // pair에서 second를 S로 줄여 사용
using namespace std;
int N, M; // N: 노드 개수, M: 간선 개수
int J, S; // J: 지헌의 출발지, S: 성하의 출발지
vector<pair<int, int>> connect[101]; // 그래프의 연결 정보를 저장 (인접 리스트)
priority_queue<pair<int, int>, vector<pair<int, int>>> q; // 다익스트라를 위한 우선순위 큐
int Distance[101]; // 특정 출발지에서 각 노드까지의 최단 거리
int J_Distance[101]; // J -> X 최단 거리 저장
int S_Distance[101]; // S -> X 최단 거리 저장
// Distance 배열을 INF로 초기화 (새로운 다익스트라 실행을 준비)
void reset_distance() {
for (int i = 1; i <= N; i++) Distance[i] = INF;
}
// 다익스트라 알고리즘: 특정 출발지(st)에서 각 노드까지의 최단 거리 계산
void Dijstra(int st) {
reset_distance(); // 거리 배열 초기화
Distance[st] = 0; // 출발지까지의 거리는 0
q.push({-Distance[st], st}); // 우선순위 큐에 초기값 삽입
while (!q.empty()) {
int x = q.top().S; // 현재 노드
int cost = -q.top().F; // 현재 노드까지의 거리
q.pop();
if (Distance[x] < cost) continue; // 이미 더 짧은 거리가 있으면 스킵
// 현재 노드의 모든 인접 노드 탐색
for (int i = 0; i < connect[x].size(); i++) {
int xx = connect[x][i].F; // 다음 노드
int n_cost = cost + connect[x][i].S; // 다음 노드까지의 거리
// 더 짧은 거리를 발견하면 업데이트
if (Distance[xx] > n_cost) {
Distance[xx] = n_cost;
q.push({-Distance[xx], xx}); // 우선순위 큐에 삽입
}
}
}
}
// 약속 장소를 찾는 메인 로직
void solve() {
int JS_distance = INF; // 지헌과 성하의 거리 합의 최소값
int Point = -1; // 최적의 약속 장소
int J_dis = INF; // 지헌으로부터 가장 가까운 거리
// 지헌 -> 모든 노드까지 최단 거리 계산
Dijstra(J);
for (int i = 1; i <= N; i++) {
J_Distance[i] = Distance[i]; // 지헌 기준 거리 저장
}
// 성하 -> 모든 노드까지 최단 거리 계산
Dijstra(S);
for (int i = 1; i <= N; i++) {
S_Distance[i] = Distance[i]; // 성하 기준 거리 저장
}
// 약속 장소 후보 탐색
for (int i = 1; i <= N; i++)
{
if (i == J || i == S) continue; // 조건 1: 지헌과 성하의 출발지는 제외
JS_distance = min(JS_distance, J_Distance[i] + S_Distance[i]); // 거리 합의 최소값 계산
}
// 조건에 맞는 최적의 약속 장소 선택
for (int i = N; i >= 1; i--)
{ // 번호가 큰 장소부터 탐색
if (i == J || i == S) continue; // 조건 1: 지헌과 성하의 출발지는 제외
if (JS_distance != J_Distance[i] + S_Distance[i]) continue; // 거리 합이 최소값이 아니면 제외
if (J_Distance[i] > S_Distance[i]) continue; // 조건 3: 지헌이 성하보다 늦게 도착하면 안 됨
if (J_dis >= J_Distance[i]) { // 지헌으로부터 가까운 장소를 선택
J_dis = J_Distance[i];
Point = i; // 최적의 약속 장소 업데이트
}
}
cout << Point; // 결과 출력
}
int main() {
cin.tie(0);
cout.tie(0);
cin >> N >> M; // 노드 수와 간선 수 입력
for (int i = 1; i <= M; i++)
{
int x, y, cost;
cin >> x >> y >> cost; // 간선 정보 입력
connect[x].push_back({y, cost}); // 양방향 간선 저장
connect[y].push_back({x, cost});
}
cin >> J >> S; // 지헌과 성하의 출발지 입력
solve(); // 약속 장소 계산
return 0;
}
노드 수: 8, 간선 수: 10
1 2 2
2 6 3
2 3 4
3 7 2
7 4 5
5 6 2
5 7 1
7 8 2
5 8 2
3 6 3
지헌의 출발지: 3, 성하의 출발지: 6
간선 데이터를 바탕으로 connect 배열이 다음과 같이 구성됩니다:
connect[1] = { {2, 2} };
connect[2] = { {1, 2}, {6, 3}, {3, 4} };
connect[3] = { {2, 4}, {7, 2}, {6, 3} };
connect[4] = { {7, 5} };
connect[5] = { {6, 2}, {7, 1}, {8, 2} };
connect[6] = { {2, 3}, {3, 3}, {5, 2} };
connect[7] = { {3, 2}, {4, 5}, {5, 1}, {8, 2} };
connect[8] = { {7, 2}, {5, 2} };
Dijkstra(3) 실행:
Distance: [INF, INF, INF, 0, INF, INF, INF, INF, INF]
우선순위 큐: { (0, 3) }
Distance: [INF, INF, 4, 0, INF, 3, 2, INF, INF]
우선순위 큐: { (2, 7), (4, 2), (3, 6) }
Distance: [INF, INF, 4, 0, 7, 3, 2, 4, INF]
우선순위 큐: { (3, 5), (4, 2), (3, 6), (7, 4), (4, 8) }
Distance (지헌 기준): [INF, INF, 4, 0, 7, 3, 2, 4, 4]
Dijkstra(6) 실행 결과:
Distance (성하 기준): [INF, INF, 3, 3, 7, 2, 0, 3, 4]
for (int i = 1; i <= N; i++) {
if (i == J || i == S) continue; // 지헌(3번), 성하(6번) 제외
JS_distance = min(JS_distance, J_Distance[i] + S_Distance[i]); // 최소 거리 합 계산
}
for (int i = N; i >= 1; i--) {
if (i == J || i == S) continue; // 조건 1: 지헌과 성하의 출발지 제외
if (JS_distance != J_Distance[i] + S_Distance[i]) continue; // 최소 거리 합 아닌 경우 제외
if (J_Distance[i] > S_Distance[i]) continue; // 조건 3: 지헌이 성하보다 늦으면 제외
if (J_dis >= J_Distance[i]) { // 지헌으로부터 가까운 장소 선택
J_dis = J_Distance[i];
Point = i; // 최적의 약속 장소 업데이트
}
}
7
int N, M;
int J, S;
vector<pair<int, int>> connect[101];
priority_queue<pair<int, int>, vector<pair<int, int>>> q;
int Distance[101];
int J_Distance[101]; // 지헌 -> 다른 노드 거리
int S_Distance[101]; // 성하 -> 다른 노드 거리
void reset_distance() {
for (int i = 1; i <= N; i++) Distance[i] = INF;
}
void Dijstra(int st) {
reset_distance();
Distance[st] = 0;
q.push({-Distance[st], st});
while (!q.empty()) {
int x = q.top().S;
int cost = -q.top().F;
q.pop();
if (Distance[x] < cost) continue;
for (int i = 0; i < connect[x].size(); i++) {
int xx = connect[x][i].F;
int n_cost = cost + connect[x][i].S;
if (Distance[xx] > n_cost) {
Distance[xx] = n_cost;
q.push({-Distance[xx], xx});
}
}
}
}
void solve() {
int JS_distance = INF; // 지헌과 성하의 최소 거리 합
int Point = -1; // 약속 장소
int J_dis = INF; // 지헌으로부터의 최소 거리
// 1. 지헌 -> 모든 노드 최단 거리 계산
Dijstra(J);
for (int i = 1; i <= N; i++) {
J_Distance[i] = Distance[i];
}
// 2. 성하 -> 모든 노드 최단 거리 계산
Dijstra(S);
for (int i = 1; i <= N; i++) {
S_Distance[i] = Distance[i];
}
// 3. 모든 노드에 대해 조건을 만족하는지 검사
for (int i = 1; i <= N; i++) {
if (i == J || i == S) continue; // 조건 1: 지헌과 성하의 출발지는 제외
JS_distance = min(JS_distance, J_Distance[i] + S_Distance[i]); // 최소 거리 합 갱신
}
// 4. 최적의 약속 장소 선택
for (int i = N; i >= 1; i--) { // 번호가 큰 장소부터 검사
if (i == J || i == S) continue;
if (JS_distance != J_Distance[i] + S_Distance[i]) continue;
if (J_Distance[i] > S_Distance[i]) continue; // 조건 3: 지헌이 성하보다 늦게 도착하면 안 됨
if (J_dis >= J_Distance[i]) {
J_dis = J_Distance[i];
Point = i;
}
}
// 5. 결과 출력
cout << Point;
}
int main() {
cin.tie(0);
cout.tie(0);
cin >> N >> M;
for (int i = 1; i <= M; i++) {
int x, y, cost;
cin >> x >> y >> cost;
connect[x].push_back({y, cost});
connect[y].push_back({x, cost});
}
cin >> J >> S;
solve();
return 0;
}
8 10
1 2 2
2 6 3
2 7 2
1 3 1
3 7 2
4 7 5
5 6 2
5 7 2
7 8 2
3 6 2
3 6
1
이 코드는 최적의 약속 장소를 정확히 찾을 수 있도록 설계되었습니다. 추가 질문이 있다면 언제든 알려주세요! 😊
Programmers 64064 불량 사용자 (0) | 2025.02.11 |
---|---|
Programmers 양과 늑대 (0) | 2025.01.22 |
백준 17825 주사위 윷놀이 (0) | 2025.01.21 |
항해//프로그래머스 60060// 가사 검색/c++// (3) | 2025.01.15 |
항해 99 //백준 11657 //타임머신//벨만 포드(Bellamn- Ford) 알고리즘 (0) | 2025.01.13 |