【PAT甲级】1146 Topological Order

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1146 Topological Order (pintia.cn)
🔑中文翻译:拓扑顺序
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

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.
>[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VRAGoXPi-1666951349623)(PAT 甲级辅导.assets/5d35ed2a-4d19-4f13-bf3f-35ed59cebf05.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
6
5 2 3 6 4 1
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:

0 4 5
题意

给定一个有向图,并给定多个序列,需要我们判断这些序列是否是拓扑序列,将不是拓扑序列的询问编号输出,询问编号从 0 开始。

拿题目样例来看,序列 [5 2 1 6 3 2] 之所以不是拓扑序列,是因为其中 2->1 方向反了。

图中只有 1->2 的边但没有 2->1 的边,不能出现逆向边,也就是每条边的前面那个点在序列中的位置必须在后面那个点的位置之前。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9AJqNlVg-1666951349626)(PAT 甲级辅导.assets/image-20221012153829409.png)]

思路

我们可以通过记录给定序列每个元素对应的下标,然后去判断每条边的两个端点的下标大小,如果是拓扑序列,则每条边 a->ba 在序列中的下标必须比 b 在序列中的下标小,即 a 在序列中的位置必须在 b 之前,否则就不是一个拓扑序列。

假设还是样例中的那张图,现在给定一个序列 [5 2 3 6 4 1] ,可以找到一条边 1->2 ,发现 1 在序列中的第 6 位,而 2 却在第 2 位,即 1 出现在了 2 的后面,所以该序列不是拓扑序列。

另外需要注意的是,输出的询问编号是从 0 开始,并且输出的末尾不能出现空格。

代码
#include<bits/stdc++.h>
using namespace std;

const int N = 1010, M = 10010;

struct Edge {
    int a, b;
}e[M];
int p[N];

int main()
{
    int n, m;
    cin >> n >> m;

    //输入每条有向边
    for (int i = 0; i < m; i++)    cin >> e[i].a >> e[i].b;

    //开始查询
    bool is_first = true; //输出行末不能有空格
    int k;
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        //输入每个序列
        for (int j = 1; j <= n; j++)
        {
            int x;
            cin >> x;
            p[x] = j; //记录每个点所在序列下标
        }

        //遍历每条边,判断是否都满足拓扑序列规则
        bool success = true;
        for (int i = 0; i < m; i++)
            if (p[e[i].a] > p[e[i].b])
            {
                success = false;
                break;
            }

        //输出不是拓扑序列的询问编号
        if (!success)
        {
            if (is_first)    is_first = false;
            else    cout << " ";
            cout << i;
        }
    }

    cout << endl;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值