PAT甲级1146Topological Order

题目链接

https://pintia.cn/problem-sets/994805342720868352/problems/994805343043829760

题解

题目要求

给定一个有向图,请判断一个序列是否是该有向图的拓扑序列。

  • 输入

    • N:正整数,不超过1000,图中顶点的数量,顶点索引为[1,N]
    • M:正整数,不超过10000,有向边的数量
    • M条有向边:开始顶点索引、结束顶点索引
    • K:不超过100,待检验的序列的个数
    • K个序列:索引为[0,K]
  • 输出

    对于每个排列,如果不是拓扑排序则输出其索引

解题思路

  1. 保存每个结点的前驱结点
  2. 使用一维数组保存每个结点是否已访问
  3. 遍历序列判断每个结点的前驱结点是否已访问,如果未访问,则该序列不是拓扑序列

代码

// Problem: PAT Advanced 1146
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805343043829760
// Tags: 拓扑序列 图

#include <iostream>
#include <vector>
using namespace std;

vector<vector<int>> before;

int main()
{
    int n, m, k;
    scanf("%d %d", &n, &m);
    before.resize(n+1);

    int v1, v2;
    for (int i = 0; i < m; i++){
        scanf("%d %d", &v1, &v2);
        before[v2].push_back(v1);
    }

    scanf("%d", &k);
    vector<int> result;
    for (int i = 0; i < k; i++){ // 判断k个序列
        // 保存一个序列
        vector<int> sequence(n);
        for (int j = 0; j < n; j++){
            scanf("%d", &sequence[j]);
        }
        // 判断该序列是否是拓扑序列
        vector<bool> visited(n + 1, false);
        bool isTopological = true;
        for (int j = 0; j < n; j++){
            v2 = sequence[j];
            for (auto iter = before[v2].begin(); iter != before[v2].end(); iter++){
                if (!visited[*iter]){
                    isTopological = false;
                    result.push_back(i);
                    break;
                }
            }
            if (isTopological)
                visited[v2] = true;
            else
                break;
        }
    }

    // 输出结果
    auto iter = result.begin();
    printf("%d", *iter);
    iter++;
    while (iter != result.end()){
        printf(" %d", *iter);
        iter++;
    }
    printf("
");

    return 0;
}

作者:@臭咸鱼

转载请注明出处:https://www.cnblogs.com/chouxianyu/

欢迎讨论和交流!


原文地址:https://www.cnblogs.com/chouxianyu/p/13676397.html