A1146 Topological Order(25分)PAT 甲级(Advanced Level) Practice(C++)满分题解【拓扑排序】

本文解析了2018年研究生入学考试中关于拓扑排序的问题,介绍了如何编写程序检测给定的顶点序列是否为合法的拓扑顺序,并提供了两个代码实现版本。关键步骤包括判断节点的入度、更新邻接表和判断序列是否符合拓扑排序条件。
摘要由CSDN通过智能技术生成

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.

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

题意分析:

这道题是有关拓扑排序,可以理解为就是按入度从小到大一个个取出节点,每取出一个节点,他对应的邻接表的所有节点的入度都要-1

在这道题中反了一下,是先知道序列再判断是否是拓扑排序,就转换为当前节点的入度是否要大于上一个节点,判断完了之后从队列中移除,并且移除节点的邻接表里的所有节点都要入度-1

这道题在写的时候要注意数组或者vector的传值问题,一开始值传递,地址传递没有搞清楚导致一直没法AC

代码如下:

2022.06.04:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m,k,v1,v2,a,flag=0,in[1010];
    cin>>n>>m;
    vector<int> v[1010];
    for(int i=1;i<=m;i++)
    {
        cin>>v1>>v2;
        v[v1].push_back(v2);
        in[v2]++;//入度
    }
    cin>>k;
    for(int i=0;i<k;i++)
    {
        int judge=1;
        vector<int> tin(in,in+n+1);
        for(int j=0;j<n;j++){
            cin>>a;
            if(tin[a]!=0)judge=0;//入度不为0,不是拓扑序列,还不能输出
            for(int it:v[a])tin[it]--;//每次选中某个点后要将它所指向的所有结点的入度-1
        }
        if(judge==1)continue;
        printf("%s%d",flag==1?" ":"",i);
        flag=1;
    }
    cout<<endl;
    return 0;
}

2022.08.10:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1010;
int n, m, k;//n个点,m条边,k个问题
vector<int> G[MAXN];//邻接表
int inDegree[MAXN] = { 0 };//每个节点的入度
bool isTopologicalSort(queue<int> q, vector<int> inDegree)
{
	//判断后一个的入度是否>=前一个的
	//每判断一个就将其出局,与它相连的那个节点的入度就-1
	int last = q.front();
	for (int i = 0; i < G[last].size(); i++) {
		inDegree[G[last][i]]--;
	}
	q.pop();
	while (!q.empty()) {
		int curr = q.front();
		if (inDegree[curr] >= inDegree[last]) {
			for (int i = 0; i < G[curr].size(); i++) {
				inDegree[G[curr][i]]--;
			}
			q.pop();
			last = curr;
		}
		else return false;
	}
	return true;
}
int main()
{
	cin >> n >> m;
	int v1, v2;
	for (int i = 0; i < m; i++) {
		cin >> v1 >> v2;
		inDegree[v2]++;
		G[v1].push_back(v2);
	}
	cin >> k;
	bool isfirst = true;
	for (int i = 0; i < k; i++) {
		int t;
		queue<int> q;
		for (int j = 0; j < n; j++) {
			cin >> t;
			q.push(t);
		}
		vector<int> ind(n + 1);
		for (int k = 1; k <= n; k++) {
			ind[k] = inDegree[k];
		}
		if (!isTopologicalSort(q, ind)) {
			if (!isfirst)cout << " " << i;
			else {
				isfirst = false;
				cout << i;
			}
		}
	} 
	return 0;
}

 

运行结果如下:

2022.06.04:

2022.08.10:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值