コース



  • オンライン講座ごとに選手講座があり、選手講座のある講座は選手講座を先に聞いてからしか受講できません.
  • 例えば、「アルゴリズム」の授業の先修科目に「データ構造」と「コンピュータ基礎」が存在する場合、「データ構造」と「コンピュータ基礎」を聞いた後、「アルゴリズム」の授業を聞くことができる.

  • 共聴N門課.すべてのコース番号は1からNまでです.
  • |複数のレッスンを同時に受講できるとします.
  • 例えば、N = 3では、3号課の先修課が1号課と2号課に先修課がないと仮定する.
  • 各レッスンの受講時間を次のように仮定します.
  • 1番課:30時間
  • 2号課:20時間
  • 3課:40時間
    この場合、1次講座までの最小時間は30時間、2次講座までの最小時間は20時間、1次講座までの最小時間は70時間である.
  • 聞きたい2授業情報があれば、3授業にかかる最短時間をそれぞれ出力するプログラムを作成してください.

  • 入力条件

  • 1行目は東彬が聞く授業数N(1≦N≦500)を与えた.

  • 次のN行では、各授業の授業時間と受講時に最初に聞く授業番号は自然数で表され、各自然数はスペースで区切られています.
  • このときの授業時間は100000以下の自然数である.

  • 各課の番号は1からNまでで構成され、各行はNで終了する.

  • しゅつりょくじょうけん
  • N受講に必要な最小時間を行ごとに出力します.
  • 1.位相整列アルゴリズムを用いて解く

    
    from collections import deque
    import copy
    
    v = int(input())
    #모든 진입차수 0으로 초기화
    indegree = [0] * (v + 1)
    graph = [[] for i in range(v + 1)]
    #각 강의 시간 0으로 초기화
    time = [0] * (v + 1)
    
    for i in range(1, v + 1):
      data = list(map(int, input().split()))
      time[i] = data[0] #첫 번째 수는 시간 정보
      for x in data[1:-1]:
        indegree[i] += 1 #진입차수 증가
        graph[x].append(i)
    
    def topology_sort():
      #수행 결과를 담을 리스트
      result = copy.deepcopy(time)
      q = deque()
    
      #처음 시작은 진입차수가 0인 노드를 큐에 삽입
      for i in range(1, v + 1):
        if indegree[i] == 0:
          q.append(i)
    
      #큐가 빌 때까지 반복
      while q:
        #큐에서 원소 꺼내기
        now = q.popleft()
    
        for i in graph[now]:
          result[i] = max(result[i], result[now] + time[i]) #현재보다 강의 시간이 오래걸리는 경우 시간 값을 저장
          indegree[i] -= 1 #진입차수 감소
          #새롭게 진입차수가 0이 되는 노드를 큐에 삽입
          if indegree[i] == 0:
            q.append(i)
    
      for i in range(1, v + 1):
        print(result[i])
    
    topology_sort()
    
    
    
    
    
    

  • 各ノードの隣接ノードを確認した場合、隣接ノードの提供時間が現在よりも長いことが判明した場合、結果テーブルを更新することで、より長い時間値を保存することで答えを得ることができます.
  • 位相整列を行い、幹線情報をチェックするたびに結果表を更新

  • 最終的には,各科目の受講最小時間を-1List変数に計上する.

  • 最初に、各レッスンの時間はNlist変数に含まれ、位相ソート関数の初期部分でresult関数を使用してtimelist変数の値をコピーし、deepcopy()list変数の値に設定します.
  • listはtime関数を使用します.単純な代入操作で値が変更された場合に問題が発生する可能性があります.|リストの値をコピーする必要がある場合はresult関数を使用します.
  • 2.C++コード

    
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    // 노드의 개수(V)
    int v;
    // 모든 노드에 대한 진입차수는 0으로 초기화
    int indegree[501];
    // 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
    vector<int> graph[501];
    // 각 강의 시간을 0으로 초기화
    int times[501]; 
    
    // 위상 정렬 함수 
    void topologySort() {
        vector<int> result(501); // 알고리즘 수행 결과를 담을 리스트 
        for (int i = 1; i <= v; i++) {
            result[i] = times[i];
        } 
        
        queue<int> q; // 큐 라이브러리 사용
    
        // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
        for (int i = 1; i <= v; i++) {
            if (indegree[i] == 0) {
                q.push(i);
            }
        }
    
        // 큐가 빌 때까지 반복
        while (!q.empty()) {
            // 큐에서 원소 꺼내기
            int now = q.front();
            q.pop();
            // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
            for (int i = 0; i < graph[now].size(); i++) {
                result[graph[now][i]] = max(result[graph[now][i]], result[now] + times[graph[now][i]]);
                indegree[graph[now][i]] -= 1;
                // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
                if (indegree[graph[now][i]] == 0) {
                    q.push(graph[now][i]);
                }
            }
        }
    
        // 위상 정렬을 수행한 결과 출력
        for (int i = 1; i <= v; i++) {
            cout << result[i] << '\n';
        }
    }
    
    int main(void) {
        cin >> v;
    
        // 방향 그래프의 모든 간선 정보를 입력받기
        for (int i = 1; i <= v; i++) {
            // 첫 번째 수는 시간 정보를 담고 있음 
            int x;
            cin >> x;
            times[i] = x;
            // 해당 강의를 듣기 위해 먼저 들어야 하는 강의들의 번호 입력 
            while (true) {
                cin >> x;
                if (x == -1) break;
                indegree[i] += 1;
                graph[x].push_back(i);
            }
        }
    
        topologySort();
    }
    

    3.Javaコード

    
    
    import java.util.*;
    
    public class Main {
    
        // 노드의 개수(V)
        public static int v;
        // 모든 노드에 대한 진입차수는 0으로 초기화
        public static int[] indegree = new int[501];
        // 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
        public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
        // 각 강의 시간을 0으로 초기화
        public static int[] times = new int[501];
    
        // 위상 정렬 함수
        public static void topologySort() {
            int[] result = new int[501]; // 알고리즘 수행 결과를 담을 배열
            for (int i = 1; i <= v; i++) {
                result[i] = times[i];
            }
    
            Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 사용
    
            // 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
            for (int i = 1; i <= v; i++) {
                if (indegree[i] == 0) {
                    q.offer(i);
                }
            }
    
            // 큐가 빌 때까지 반복
            while (!q.isEmpty()) {
                // 큐에서 원소 꺼내기
                int now = q.poll();
                // 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
                for (int i = 0; i < graph.get(now).size(); i++) {
                    result[graph.get(now).get(i)] = Math.max(result[graph.get(now).get(i)], result[now] + times[graph.get(now).get(i)]);
                    indegree[graph.get(now).get(i)] -= 1;
                    // 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
                    if (indegree[graph.get(now).get(i)] == 0) {
                        q.offer(graph.get(now).get(i));
                    }
                }
            }
    
            // 위상 정렬을 수행한 결과 출력
            for (int i = 1; i <= v; i++) {
                System.out.println(result[i]);
            }
        }
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            v = sc.nextInt();
    
            // 그래프 초기화
            for (int i = 0; i <= v; i++) {
                graph.add(new ArrayList<Integer>());
            }
    
            // 방향 그래프의 모든 간선 정보를 입력받기
            for (int i = 1; i <= v; i++) {
                // 첫 번째 수는 시간 정보를 담고 있음 
                int x = sc.nextInt();
                times[i] = x;
                // 해당 강의를 듣기 위해 먼저 들어야 하는 강의들의 번호 입력 
                while (true) {
                    x = sc.nextInt();
                    if (x == -1) break;
                    indegree[i] += 1;
                    graph.get(x).add(i);
                }
            }
    
            topologySort();
        }
    }