본문 바로가기

Problem Solving/문제풀이

[BOJ] 1005 ACM Craft

문제: https://www.acmicpc.net/problem/1005


 위상 정렬의 대표격인 건설 순서 문제이다. 그런데 사실 난이도가 아주 없는 문제는 아니어서 이게 왜 1005번에 있나 조금 의심이 들기는 하는 부분이다. 사실 습격자 초라기에 비할 바는 못되지만...

 하여튼 내 풀이를 설명하자면, DFS를 이용해 그래프를 순회하면서 함수가 종료할 때마다 저장하면 위상 정렬의 역순이 된다는 점을 이용해서 DP를 돌리는 방법으로 문제를 풀었다. 이를 위해서 순방향 간선과 역방향 간선의 인접 리스트를 별도로 만들었고, 역방향 간선의 인접 리스트의 크기가 0인 것들을 모두 DFS 돌리고 reverse해서 위상 정렬을 찾은 다음 그걸 역방향 간선 인접 리스트를 통해 바텀업 DP로 돌려서 결과값을 찾아냈다.

 그런데 다른 블로그를 뒤적거려 보니까 그냥 탑다운으로 DFS를 돌리면서 다이나미컬 백트래킹으로 구현하는 편이 훨씬 나았을 것 같다. 하여튼 그건 기회 되면 짜 보기로 하고 일단은 위상 정렬을 찾는 것과 바텀업 DP(라고 하기 뭐한 것)을 연습했다는 것에 의의를 두고 싶다.

 개인적인 감상이지만 내가 짠 코드가 너무 심하게 복잡하고 난해하다. 난이도는 2/5정도 되는 듯.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <vector>
#include <cstdio>
#include <algorithm>
 
using namespace std;
 
void dfs(vector<vector<int> > &lis, vector<int> &check, vector<int> &s, int x)
{
    check[x]=1;
    vector<int> &here=lis[x];
    for(int i=0;i<here.size();i++)
    {
        if(check[here[i]]==1continue;
        dfs(lis,check,s,here[i]);
    }
    s.push_back(x);
}
 
void solve()
{
    int n,m;
    scanf("%d %d",&n,&m);
    vector<int> time(n+1);
    vector<vector<int> > lis(n+1,vector<int>()), ed(n+1,vector<int>());
    vector<int> check(n+1,0), dp(n+1,-1);
    vector<int> s;
    for(int i=1;i<=n;i++)
    {
        int t;
        scanf("%d",&t);
        time[i]=t;
    }
    for(int i=0;i<m;i++)
    {
        int t1,t2;
        scanf("%d %d",&t1,&t2);
        lis[t1].push_back(t2);
        ed[t2].push_back(t1);
    }
 
    for(int i=1;i<=n;i++)
    {
        if(ed[i].size()!=0continue;
        dfs(lis,check,s,i);
        dp[i]=time[i];
    }
    reverse(s.begin(),s.end());
 
    for(auto it=s.begin();it!=s.end();it++)
    {
        int k=*it;
        if(dp[k]!=-1continue;
        for(auto jt=ed[k].begin();jt!=ed[k].end();jt++)
            dp[k]=max(dp[k],dp[*jt]);
        dp[k]+=time[k];
    }
 
    int w;
    scanf("%d",&w);
    printf("%d\n",dp[w]);
}
 
int main()
{
    int tc;
    scanf("%d",&tc);
    while(tc--)
        solve();
    return 0;
}
 
cs


 

'Problem Solving > 문제풀이' 카테고리의 다른 글

[BOJ] 1922 네트워크 연결  (0) 2018.02.02
[BOJ] 1931 회의실배정  (0) 2018.02.02
[BOJ] 2439 탑  (0) 2018.02.01
[BOJ] 1011 Fly me to the Alpha Centauri  (1) 2018.02.01
[BOJ] 1918 후위표기식  (0) 2018.02.01