zoukankan      html  css  js  c++  java
  • 1146 Topological Order

    This is a problem given in the Graduate Entrance Exam in 2018: Which of the following is NOT a topological order obtained from the given directed graph? Now you are supposed to write a program to test each of the options.

    gre.jpg

    Input Specification:

    Each input file contains one test case. For each case, the first line gives two positive integers N (≤ 1,000), the number of vertices in the graph, and M (≤ 10,000), the number of directed edges. Then M lines follow, each gives the start and the end vertices of an edge. The vertices are numbered from 1 to N. After the graph, there is another positive integer K (≤ 100). Then K lines of query follow, each gives a permutation of all the vertices. All the numbers in a line are separated by a space.

    Output Specification:

    Print in a line all the indices of queries which correspond to "NOT a topological order". The indices start from zero. All the numbers are separated by a space, and there must no extra space at the beginning or the end of the line. It is graranteed that there is at least one answer.

    Sample Input:

    6 8
    1 2
    1 3
    5 2
    5 4
    2 3
    2 6
    3 4
    6 4
    5
    1 5 2 3 6 4
    5 1 2 6 3 4
    5 1 2 3 6 4
    5 2 1 6 3 4
    1 2 3 4 5 6
    
     

    Sample Output:

    3 4

    题意:

      给出一个拓扑图判断,所给的序列是不是拓扑排序。

    思路:

      用连接矩阵来存储拓扑图,判断是不是拓扑序列的时候,只需要检查还有没有指向这个节点的边。如果没有指向这个节点的边,就将所有以这个结点为起点的边删除。

    Code:

    #include <iostream>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    int main() {
        int n, m;
        cin >> n >> m;
    
        int s, e;
        vector<vector<int> > grap(n + 1, vector<int>(n + 1, 0));
        for (int i = 0; i < m; ++i) {
            cin >> s >> e;
            grap[s][e] = 1;
        }
    
        int k, t;
        cin >> k;
        bool isTopo = true;
        vector<int> ans;
        vector<vector<int> > dummy;
        for (int i = 0; i < k; ++i) {
            isTopo = true;
            dummy = grap;
            for (int j = 0; j < n; ++j) {
                cin >> t;
                for (int k = 1; k <= n; ++k) {
                    if (dummy[k][t] != 0)
                        isTopo = false;
                    else {
                        dummy[t][k] = 0;
                    }
                }
            }
            if (!isTopo) ans.push_back(i);
        }
        cout << ans[0];
        for (int i = 1; i < ans.size(); ++i) {
            cout << " " << ans[i];
        }
        cout << endl;
    
        return 0;
    }

    上面的代码最后一组数据超时,又优化了一下代码,通过了全部的测试点。

    #include <iostream>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    int main() {
        int n, m;
        cin >> n >> m;
    
        int s, e;
        vector<vector<int> > grap(n + 1, vector<int>(n + 1, 0));
        for (int i = 0; i < m; ++i) {
            cin >> s >> e;
            grap[s][e] = 1;
        }
    
        int k, t;
        cin >> k;
        vector<int> ans, temp;
        vector<vector<int> > dummy;
        for (int i = 0; i < k; ++i) {
            dummy = grap;
            temp.clear();
            for (int j = 0; j < n; ++j) {
                cin >> t;
                temp.push_back(t);
            }
            bool flag = false;
            for (int j = 0; j < n; ++j) {
                for (int k = 1; k <= n; ++k) {
                    if (dummy[k][temp[j]] == 1) {
                        flag = true;
                        ans.push_back(i);
                        break;
                    } else
                        dummy[temp[j]][k] = 0;
                }
                if (flag) break;
            }
        }
        cout << ans[0];
        for (int i = 1; i < ans.size(); ++i) {
            cout << " " << ans[i];
        }
        cout << endl;
    
        return 0;
    }

    参考了一下别人的代码,变更了一种解体的思路,代码也更加的简洁。

     1 #include <iostream>
     2 #include <queue>
     3 #include <vector>
     4 
     5 using namespace std;
     6 
     7 int main() {
     8     int n, m;
     9     cin >> n >> m;
    10 
    11     int s, e;
    12     vector<int> v[n+1], in(n+1, 0);
    13     for (int i = 0; i < m; ++i) {
    14         cin >> s >> e;
    15         v[s].push_back(e);
    16         in[e]++;
    17     }
    18     int k, t;
    19     cin >> k;
    20     vector<int> ans;
    21     for (int i = 0; i < k; ++i) {
    22         bool flag = true;
    23         vector<int> temp = in;
    24         for (int j = 0; j < n; ++j) {
    25             cin >> t;
    26             if (temp[t] != 0) flag = false;
    27             for (int it : v[t]) 
    28                 temp[it]--;
    29         }
    30         if (!flag) ans.push_back(i);
    31     }
    32 
    33     int isFirst = true;
    34     for (int i = 0; i < ans.size(); ++i) {
    35         if (isFirst) {
    36             cout << ans[i];
    37             isFirst = false;
    38         } else {
    39             cout << " " << ans[i];
    40         }
    41     }
    42 
    43     return 0;
    44 }

      这种方法是通过记录每个节点的入度,根据遍历的过程中是否有入度不为0的结点来判断所给序列是不是拓扑排序。

    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    进程间通信之数据共享--共享内存
    进程间通信之分工协作-信号灯
    进程间通信之分工协作--锁
    进程间通信之事件通知--信号
    进程间通信之数据传输--Socket
    c++模板特化
    DAG模型:嵌套矩形
    数字三角形
    c柔性数组结构成员
    模板
  • 原文地址:https://www.cnblogs.com/h-hkai/p/12692841.html
Copyright © 2011-2022 走看看