三星研究院上机题(Order of task)

  • Post author:
  • Post category:其他



Thereare V tasks to do. Some task(s) can begin only after a particular task ends,which we will call precedence relation. A graph indicating precedence relationof tasks is given. In this graph, each task is denoted as vertex, and the precedencerelation as directed edge. Note there is no cycle with this graph (cycle refers to a path that starts from one vertex and returns to the same vertex). The graph below is one example of such graph





In this graph, task 1 can start after task 4 ends and task 6can when task 5 and task 7 end; there is no cycle with this graph.


Manager Kim is going to finish a set of tasks having precedencerelation by taking care of one task at a time. If he is going to do this withthe set of tasks illustrated above, the tasks can be handled with the followingorder.


8, 9, 4, 1, 5, 2, 3, 7, 6


And the order below is also possible.


4, 1, 2, 3, 8, 5, 7, 6, 9


But, the order below is not possible.


4, 1, 5, 2, 3, 7, 6, 8, 9


With this order, task 5 is handled earlier that task 8, but inthe precedence relation given in the graph above, task 5 can only begin whentask 8 ends so this order is not possible.


Given V tasks and their precedence relations, write a programthat finds the order by which one person can does one task at a time. Usuallythere are a number of possible orders so all you need to do is present just oneof them. Since a graph with a cycle is not given in input, you don


’t need toconsider error-handling in such case. In the graph with no cycle, possibleorder(s) always exist.


输出任务序列


[Constraints]


The total number of vertices, V, in the graph is 5





V





1000.


Time limit: 1 sec for 10 test cases combined


[Input]


10 test cases are given. Throughout 20 lines, one test case isgiven for every two lines. In the first line of each test case, the totalnumber of graph


’s vertices, V, and the total number of edges, E, are given. Inthe next line, E edges are arranged; edges are denoted as comprising twovertices. For example, the edge connecting from vertex 5 to vertex 28 is denotedas “5 28”. The vertex numbers are integers from 1 to V and two neighboringnumbers in the input are separated by a blank space.


[Output]


Print answers for each of the 10 test cases line-by-linethroughout 10 lines. Start each line with


‘#x’, leave a blank space, and recordthe order of tasks. For the order of tasks, arrange V integers with a blankspace in-between.


[Input/output example]


Input




9 9





Test case 1 starts


4 1 1 2 2 3 2 7 5 6 7 6 1 5 8 5 8 9


5 4





Test case 2 starts


1 2 2 3 4 1 1 5




Output(consisting of 10 lines in total)


#1 8 9 4 1 5 2 3 7 6


#2 4 1 2 3 5





思路:拓扑排序,这题很没意思,没有做过多的限制,有很多种输出的结果,无法判断程序结果是否正确。

①给出n个点,m条边(n个点分别是1~n发布的,可以充分利用数组下标)

②记录入度和父亲即可,去除父亲节点时,要把孩子的入度减一。(


源码及数据下载



错误代码:没有考虑多父亲节点会覆盖的问题

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    freopen("1.txt","r",stdin);
    freopen("2.txt","w",stdout);
    int n,m,x,y;
    while(~scanf("%d%d",&n,&m)){
        //充分利用下标
        int a[10005][2]={0};
        for(int i=0;i<m;i++){
            scanf("%d%d",&x,&y);
            a[y][0]++;   //记录入度
            a[y][1]=x;   //记录父亲
        }
        int visit[10005]={0};
        for(int j=0;j<n;j++){       //依次找到j个点
            int index=0;
            for(int i=1;i<=n;i++){   //找到一个入度为0的点,break
                if(a[i][0]==0&&visit[i]==0){
                    visit[i]=1;
                    index=i;
                    printf("%d ",index);
                    break;
                }
            }
            //遍历哪些点的父亲为index
            for(int i=1;i<=n;i++){
                if(visit[i]==0&&a[i][1]==index) a[i][0]--;
            }
        }
        printf("\n");
    }
    return 0;
}

①用一个二维数组标记,Map[][]表示两者之间存在边的情况,这样空间复杂度和时间复杂度都会高一些。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int Map[1005][1005];
int main(){
    freopen("1.txt","r",stdin);
    freopen("2.txt","w",stdout);
    int n,m,x,y;
    while(~scanf("%d%d",&n,&m)){
        //充分利用下标
        int a[1005]={0};
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            Map[i][j]=0;
        for(int i=0;i<m;i++){
            scanf("%d%d",&x,&y);
            a[y]++;   //记录入度
            Map[x][y]=1;
        }
        int visit[1005]={0};
        for(int j=0;j<n;j++){       //依次找到j个点
            int index=0;
            for(int i=1;i<=n;i++){   //找到一个入度为0的点,break
                if(a[i]==0&&visit[i]==0){
                    visit[i]=1;
                    index=i;
                    printf("%d ",index);
                    break;
                }
            }
            //遍历哪些点的父亲为index
            for(int i=1;i<=n;i++){
                if(visit[i]==0&&Map[index][i]==1) a[i]--;
            }
        }
        printf("\n");
    }
    return 0;
}

②在原基础上,用一个vector存储所用的孩子节点,然后删除当前父节点的所有孩子节点。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> V[1005];
int main(){
    freopen("1.txt","r",stdin);
    freopen("2.txt","w",stdout);
    int n,m,x,y;
    while(~scanf("%d%d",&n,&m)){
        //充分利用下标
        int a[1005]={0};
        for(int i=0;i<m;i++){
            scanf("%d%d",&x,&y);
            a[y]++;   //记录入度
            V[x].push_back(y);
        }
        int visit[1005]={0};
        for(int j=0;j<n;j++){       //依次找到j个点
            int index=0;
            for(int i=1;i<=n;i++){   //找到一个入度为0的点,break
                if(a[i]==0&&visit[i]==0){
                    visit[i]=1;
                    index=i;
                    printf("%d ",index);
                    break;
                }
            }
            //遍历哪些点的父亲为index
            for(int i=0;i<V[index].size();i++){
                a[V[index][i]]--;
            }
            V[index].clear();
        }
        printf("\n");
    }
    return 0;
}

③队列,第一步存储所有入度为0的结点,第二步依次把相连的结点入度减1,且满足条件入队。


参考代码



版权声明:本文为hqh131360239原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。