Нужна помощь, чтобы найти наименьшее количество семестров

#java #topological-sort

#java #топологическая сортировка

Вопрос:

В моей задаче с домашним заданием представлены некоторые курсы и сколько из них зависят друг от друга. Например, первый тест (курсы, зависящие от): (1,3) (2,3) (4,1) (4,2) и мы определяем, что существует 5 курсов и 4 зависят друг от друга (вот почему 5 нет в списке, это просто 0)

Я знаю из топологического поиска, что следующее является допустимым решением: 1 3 2 4 0

Затем мне нужно вывести количество семестров, необходимое для прохождения этих курсов, и я знаю, что это 3 семестра, из-за отношений между ними. Сначала нам нужно пройти курсы 1 и 2, чтобы пройти курс 3, и поскольку у нас уже есть 1-2, мы можем пройти курс 4.

Итак, мне нужна помощь в определении некоторого кода, который делает это. Вот где мне нужна ваша помощь, ребята

Я пытался просто посчитать подключенные курсы, но не получилось. Я пытался придумать что-нибудь, что я могу сделать, но буквально ничего не всплывает в качестве решения.

Класс graph:

 public class Graph {

    int V;
    LinkedList<Integer> adjList[];

    public Graph(int vertex) {
        this.V = vertex;

        //We then define the num of vertexes in the adjlist
        adjList = new LinkedList[vertex];

        //Then create a new list for each vertex so we can create a link between the vertexes
        for (int i = 0; i < vertex; i  ) {
            adjList[i] = new LinkedList<>();
        }
    }
    //Directed graph
    public void addEdge(int source, int destination) {
        //Add the edge from the source node to the destination node

        adjList[source].add(destination);
        adjList[destination].add(source);
    }

    //Method to print the graph if necessary
    public void printGraph(Graph graph) {
        for (int i = 0; i < graph.V; i  ) {
            System.out.println("Adjacency list over vertex: "   i);
            System.out.print("head");

            for (Integer treeCrawler : graph.adjList[i]) {

                System.out.print("-> "   treeCrawler);
            }
            System.out.println("n");
        }
    }

    public LinkedList<Integer>[] getAdjList() {
        return adjList;
    }
}
  

и класс топологической сортировки, алгоритм, который мы используем для решения задачи

 public class TopologicalSort {

    int vertex;

    //This function helps the topological function recursively by marking the vertices and pushing them onto the stack
    public void topologicalHelper(int vertex, boolean marked[], Stack nodes, Graph graph) {

        List<Integer>[] list = graph.getAdjList();

        marked[vertex] = true;

        Iterator<Integer> iterator = list[vertex].iterator();
        while (iterator.hasNext()) {
            int temp = iterator.next();
            if (!marked[temp] amp;amp; list[temp].size() != 0) {
                topologicalHelper(temp, marked, nodes, graph);
            }

        }
        nodes.add(vertex);
    }


    public TopologicalSort(Graph graph, int vertecies) {
        vertex = vertecies;
        Stack nodes = new Stack();
        boolean[] marked = new boolean[vertex];

        for (int i = 0; i < vertex; i  ) {
            if (marked[i] == false) {
                topologicalHelper(i, marked, nodes, graph);
            }
        }
        while(!nodes.empty()) {
            System.out.print(nodes.pop()   " ");
        }
    }
}
  

Результатом должно быть 3, но я не привел это число во всех своих идеях решения, мне нужна помощь или подсказки.


О, и ниже приведен вывод консоли

 Adjacency list over vertex: 0
head

Adjacency list over vertex: 1
head-> 3-> 4

Adjacency list over vertex: 2
head-> 3-> 4

Adjacency list over vertex: 3
head-> 1-> 2

Adjacency list over vertex: 4
head-> 1-> 2

1 3 2 4 0 
  

Ответ №1:

Зависимость — это направленное свойство, поэтому вы должны использовать ориентированный граф. После заполнения графика u в конечном итоге получит несвязанный график, в котором есть одно или несколько деревьев. Выясните, какие узлы являются корнями каждого дерева, и используйте DFS, чтобы получить максимальную глубину каждого дерева. Предполагая, что нет ограничений на количество курсов для каждого семестра, максимальная глубина всех деревьев является решением.

 public class Graph {
int V;
ArrayList<Integer> adjList[];
boolean[] notRoot;
public Graph(int vertex) {
    this.V = vertex;
    adjList = new ArrayList[vertex];
    notRoot = new boolean[vertex];
    for (int i = 0; i < vertex; i  ) {
        adjList[i] = new ArrayList<Integer>();
    }
}
public void addEdge(int a, int b) {
    //asuming b is dependent on a
    adjList[b].add(a);
    notRoot[a]=true;
}
int maxDepthDfs(int root){
    int depth=1;
    for(int i=0;i<adjList[root].size();i  ){
        int child=adjList[root].get(i);
        depth=Math.max(maxDepthDfs(child) 1,depth);
    }
    return depth;
}
public int getSolution(){
    int ans=0;
    for(int i=0;i<V;i  ){
        if(!notRoot[i])
            ans=Math.max(ans,maxDepthDfs(i));
    }
    return ans;
}
}
  

Топологическая сортировка — это просто DFS с добавлением узлов в стек (сначала добавляются все дочерние узлы узла, а затем добавляется root). В алгоритме Кана сначала найдены корневые элементы (узлы без родительских), и метод вызывается только для этих узлов.

 int maxDepthDfs(int root){
//since we are only calling this function for root nodes we need not check if nodes were previously visited
int depth=1;
for(int i=0;i<adjList[root].size();i  ){
    int child=adjList[root].get(i);
    depth=Math.max(maxDepthDfs(child) 1,depth);
}
s.push(root);
return depth;
}
public int getSolution(){
    s=new Stack<Integer>();
    int ans=0;
    for(int i=0;i<V;i  ){
        if(!notRoot[i])
            ans=Math.max(ans,maxDepthDfs(i));
    }
    //stack s contains result of topological sort;
    return ans;
}
  

Комментарии:

1. О, ну, вопрос рассматривался как топологическая сортировка, предположительно, практика в алгоритме. Но спасибо вам за решение, я не думал об этом так, как указано, но это, безусловно, имеет смысл.