개인사
[G2] 백준 14907번 프로젝트 스케줄링 C++ 위상 정렬, 파싱, 해시맵 본문
728x90

리뷰

https://www.acmicpc.net/problem/14907
오랜만에 풀어본 위상 정렬 + 파싱 문제, 재미있었다.
전역 변수
- cnt : 자신에게 들어오는 간선의 개수를 저장할 해시맵
- weights : 자신의 가중치를 저장할 해시맵
- pre_sum : 자신에게 누적된 가중치의 최대값을 저장할 해시맵
- edges : 자신으로 부터 갈 수 있는 노드를 저장한 인접 리스트 해시맵
함수
1. Split
vector< string > Split(const string& s)
{
stringstream ss( s );
vector< string > args;
string temp = "";
while ( getline( ss, temp, ' ' ) )
args.push_back( temp );
return args;
}
개행문자를 기준으로 문자열을 입력 받아 각 인자를 파싱하기 위한 함수
2. ParsingAndInitialize
void ParsingAndInitialize(const string& s)
{
vector< string > args = Split( s );
char node = args[ 0 ][ 0 ];
weights[ node ] = stoi( args[ 1 ] );
string conn = args.size() > 2 ? args[ 2 ] : "";
if ( !cnt.count( node ) )
cnt[ node ] = 0;
for ( int i = 0; i < ( int )conn.size(); ++i )
{
char nextNode = conn[ i ];
edges[ nextNode ].push_back( node );
++cnt[ node ];
}
}
파싱한 데이터를 기반으로 자료 구조의 초기값을 초기화 하기 위한 함수
3. Input
void Input()
{
string s;
while ( getline( cin, s ) )
{
if ( s.empty() )
break;
ParsingAndInitialize( s );
}
}
입력 및 초기화를 담당하는 함수
문제풀이
- Input함수를 호출하여 입력, 파싱, 초기화를 진행한다.
- 변수 mx를 0으로 초기화 하고, 문자 타입 큐 q를 초기화한다.
- cnt를 순회하며 value가 0인 경우 q에 key를 추가하고, 해당 노드의 pre_sum을 weights값으로 초기화한다.
- q가 빌때까지 while루프를 수행하고, 매 루프마다 문자 변수 node에 q의 front값을 저장, pop처리한다.
- mx를 mx와 pre_sum[node] 중 더 큰 값으로 저장한다.
- edges[node]를 순회하고, 문자 변수 nextNode에 다음 노드를 저장한다.
- pre_sum[nextNode]의 값을, pre_sum[node] + weights[nextNode]와 비교해 더 큰 값으로 저장한다.
- cnt[nextNode]를 1만큼 감소시키고, 값이 0이 된 경우 q에 nextNode를 추가한다.
- while루프가 종료된 후 mx에 저장된 값을 출력한다.
트러블 슈팅
없음
참고 사항
- 작업의 개수나 작업으로 들어오는 영문 대문자가 순차적이라는 말이 없어 해시맵을 사용해 주었다.
- 작업을 시작하기 전에 완료해야만 하는 작업의 개수도 주어지지 않았으므로 getline으로 한줄을 입력으로 받았다.
- stringstream을 통해 공백을 기준으로 각 요소를 파싱하였다.
정답 코드
#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <sstream>
#include <unordered_map>
using namespace std;
unordered_map< char, int > cnt;
unordered_map< char, int > weights;
unordered_map< char, int > pre_sum;
unordered_map< char, vector< char > > edges;
vector< string > Split(const string& s)
{
stringstream ss( s );
vector< string > args;
string temp = "";
while ( getline( ss, temp, ' ' ) )
args.push_back( temp );
return args;
}
void ParsingAndInitialize(const string& s)
{
vector< string > args = Split( s );
char node = args[ 0 ][ 0 ];
weights[ node ] = stoi( args[ 1 ] );
string conn = args.size() > 2 ? args[ 2 ] : "";
if ( !cnt.count( node ) )
cnt[ node ] = 0;
for ( int i = 0; i < ( int )conn.size(); ++i )
{
char nextNode = conn[ i ];
edges[ nextNode ].push_back( node );
++cnt[ node ];
}
}
void Input()
{
string s;
while ( getline( cin, s ) )
{
if ( s.empty() )
break;
ParsingAndInitialize( s );
}
}
int main()
{
ios::sync_with_stdio( 0 );
cin.tie( 0 );
Input();
int mx = 0;
queue< char > q;
for ( const auto& [k, v] : cnt )
{
//cout << k << " " << v << "\n";
if ( !v )
{
q.push( k );
pre_sum[ k ] = weights[ k ];
}
}
while ( !q.empty() )
{
char node = q.front(); q.pop();
//cout << node << " " << pre_sum[ node ] << "\n";
mx = max( mx, pre_sum[ node ] );
for ( const char& nextNode : edges[ node ] )
{
pre_sum[ nextNode ] = max( pre_sum[ nextNode ], pre_sum[ node ] + weights[ nextNode ] );
if ( !--cnt[ nextNode ] )
q.push( nextNode );
}
}
cout << mx;
}728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
| [G5] 백준 14588번 Line Friends (Small) C++ 플로이드 와샬, 최단 거리 (0) | 2026.03.19 |
|---|---|
| [G5] 백준 34949번 이대로 가면 되나요? C++ BFS, 너비 우선 탐색 (0) | 2026.03.16 |
| [G5] 백준 30470번 호반우가 학교에 지각한 이유 3 C++ map, 트리맵, upper_bound (0) | 2026.03.10 |
| [G5] 백준 30702번 국기 색칠하기 C++ 너비 우선 탐색, 플러드 필 (0) | 2026.03.08 |
| [G4] 백준 6195번 Fence Repair C++ 그리디 알고리즘, 우선순위 큐 (0) | 2026.03.06 |
