Topological sorting solves the problem of the first class

  Problem: There are n courses in a college, (i, j) means that course i is the predecessor of course j, that is, course i must be offered in the semester before course j. For any given set of preceding classes S={(1,3),(2,4),(3,5),(4,6),(3,7).}, how many semesters should be arranged at least? Give a list of courses offered each semester. 
  Analysis: The most common type of solution to the problem of the first class is topological sorting. A simple understanding of topological sorting is to continuously find nodes with zero in-degree in the graph, and treat each batch of nodes with zero in-degree as a class in the same semester. Output, and then reduce the in-degree of the nodes pointed to by this batch of nodes by one. At this point, the in-degrees of all nodes are reshuffled, and the previous operations are repeated to continue to find nodes with zero in-degrees. until all nodes have been picked.

  Fake code:

while (find the i-th node with zero in-degree)
{
    indegree[ith batch of nodes];
    Output the i-th batch of nodes as a semester's course;
    indegree[all nodes pointed to by the i-th batch of nodes]--;
}
  Encapsulate the variables and functions needed to solve the problem in a class
class course//course类
{
public:
    course(int n=1)
    {//Define the constructor of the course class
        num=n
        indegree=new int[n+1];
        edge=new vector<int>[n+1];
        memset(indegree,0,sizeof(int)*(n+1));//Set the indegree array to zero
    }
    void getIndegree();//Get the in-degree of each node according to the input set of preceding classes, and put it into the array indegree
    void topologicalSort();//Topological sort to get the courses of each semester
private:
    stack<int> zeroInd;//Used to record each batch of nodes with zero in-degree
    int *indegree;//Record the in-degree of each node
    int num;//Record the number of courses
    vector<int> *edge;//Record the next node pointed to by each node
    bool findZeroInD();//Private function, find the node with zero in-degree and put it on the stack zeroInd
};
  At the beginning, I did not introduce the course class, but directly defined the global arrays indegree and edge. To zero the indegree array only needs to be
int indegree[200]={0};
  After the introduction of the course class, dynamic allocation of memory space is used
indegree=new int[n+1]; edge=new vector<int>[n+1];

  It is necessary to use the memset function to zero it. At the beginning, I directly memset(indegree,0,sizeof(indegree)); and found that I could not get the correct result. Later, I thought that the problem lies in sizeof(indegree), because at this time indegree is used as an int pointer variable, not as an array, so sizeof(indegree) should be the size of int* type variable at this time, generally four bytes, Instead of equal to the size of the memory space we allocated, if you want to represent the size of the allocated memory space, you need sizeof(int)*(n+1), change to memset(indegree,0,sizeof(int)*(n+ 1)); the correct result can be obtained. Some people may doubt that the correct result can be obtained by using sizeof (array name) before, that is because the array name is declared at the beginning, such as int a[10];, and in this question, indegree is actually int type of pointer.

  The implementation of each member function is given below

void course::getIndegree()
{
    int x,y;
    while(scanf("%d%d",&x,&y)==2)
    {
        if(x==y) continue;
        edge[x].push_back(y);
        indegree[y]++;
        //printf("%d %d %d\n",x,y,indegree[y]);
    }
}
bool course::findZeroInD()
{
    int cnt=0;
    for(int i=1;i<=num;i++)
    {
        if(!indegree[i])
        {
            //printf("%d\n",i);
            zeroInd.push(i);
            indegree[i]--;
            cnt++;
        }
    }
    return cnt!=0;
}
void course::topologicalSort()
{
    int semester=1,cnt=num;
    while(findZeroInD())
    {
        printf("Semester %d :\n",semester++);
        int t;
        while(!zeroInd.empty())
        {
            t=zeroInd.top();zeroInd.pop();cnt--;
            printf("%d ",t);
            for(int i=0;i<edge[t].size();i++)
            {
                indegree[edge[t][i]]--;
            }
        }
        putchar('\n');
    }
    if(cnt==0)
        printf("At least %d semesters are required\n",semester-1);
    else
        printf("There are %d courses remaining, there is a closed loop in the previous class schedule\n",cnt);
}

  After understanding the idea of ​​topological sorting, it is not difficult to understand the above function implementation process. The only thing to note is that I added a judgment on whether there is a closed loop in the previous class schedule in the topologicalSort() function, and added a counter cnt. Every time I get a node with zero in-degree, I will cnt--. If the last cnt is If it is zero, the class schedule is a DAG, and the topological sequence can be obtained. Otherwise, there is a closed loop in the graph, and the topological sequence cannot be obtained.

  The main function and test data are given below

intmain()
{
    int n;
    freopen("data.txt","r",stdin);
    scanf("%d",&n);
    course c(n);
    c.getIndegree();
    c.topologicalSort();
    return 0;
}
  
//data.txt
8
1 2
3 4
2 5
3 6
1 5
7 8
8 1
1 3



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324814412&siteId=291194637