第一次做拓扑排序的题。
题目大意是给定一组字母的大小关系判断它们是否能组成唯一的拓扑序列。
代码写的有点乱,因为思路上比较混乱点。
一般来说,在一个有向无环图中,用 BFS 进行拓扑排序是比较常见的做法
1.把所有入度为 0 的节点放进队列 Q
2 WHILE: Q 不是空队列
3.从 Q 中取出队列首元素 a,把 a 添加到答案的尾部。
4.FOR:所有从 a 出发的边 a → b
题目大意是给定一组字母的大小关系判断它们是否能组成唯一的拓扑序列。
代码写的有点乱,因为思路上比较混乱点。
一般来说,在一个有向无环图中,用 BFS 进行拓扑排序是比较常见的做法
1.把所有入度为 0 的节点放进队列 Q
2 WHILE: Q 不是空队列
3.从 Q 中取出队列首元素 a,把 a 添加到答案的尾部。
4.FOR:所有从 a 出发的边 a → b
5.把 b 的入度减 1。如果 b 的入度变为 0,则把 b 放进队列 Q。
在网上看了很多种版本,有直接用floyd来做的,有用栈的,但我还是比较偏向于用队列+vector来做,这样感觉比较对味。
/*
ID: sdj22251
PROG: calfflac
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAX 100000000
#define LOCA
#define PI acos(-1.0)
using namespace std;
int n, m;
int in[60], tmp[60];
char ans[60];
vector<int>v[60];
int top()
{
queue<int>q;
int i, cnt = 0, value = 3; // value等于3 代表可以构成唯一拓扑序列
for(i = 1; i <= n; i++)
if(in[i] == 0)
{
q.push(i);
cnt++;;
}
if(cnt > 1) value = 1; // 说明入度为0的点不唯一,拓扑序列无法确定,但是底下还要找环,所以先不要return
if(cnt == 0) return 2; //找不到入度为0的点,说明一定有环
int ct = 0;
while(!q.empty())
{
int first = q.front();
ans[ct++] = first + 'A' - 1; //存储序列
q.pop();
int size = v[first].size();
cnt = 0;
for(i = 0; i < size; i++)
{
int can_reach = v[first][i];
in[can_reach]--; //将能够连接的点的入度通通都减1
if(in[can_reach] == 0)
{
q.push(can_reach);
cnt++;
}
}
if(cnt > 1) // 入度为0的点不唯一,说明无法确定该序列
return 1;
}
if(ct < n) return 2; //序列个数不够n,说明一定有环
return value; //以上条件都没成立 说明拓扑序列唯一
}
int main()
{
#ifdef LOCAL
freopen("ride.in","r",stdin);
freopen("ride.out","w",stdout);
#endif
char s[5];
int i, x, y, j, res;
while(scanf("%d%d", &n, &m) != EOF)
{
if(n == 0 && m == 0)
break;
memset(in, 0, sizeof(in));
memset(tmp, 0, sizeof(tmp));
memset(ans, 0, sizeof(ans));
for(i = 0; i <= 30; i++)
v[i].clear();
int flag = 0, number;
for(i = 1; i <= m; i++)
{
scanf("%s", s);
x = s[0] - 'A' + 1;
y = s[2] - 'A' + 1;
v[x].push_back(y);
tmp[y]++; //tmp数组的意义是保护所有边得入度不被破坏
for(j = 1; j <= 30; j++)
in[j] = tmp[j];
if(flag == 2 || flag == 3) //有环出现或者拓扑序列已经确定,就不往下进行了
continue;
res = top();
if(i == m && res == 1)
flag = 1;
else if(res == 2)
{
flag = 2;
number = i;
}
else if(res == 3)
{
flag = 3;
number = i;
}
}
if(flag == 1 || m == 0) puts("Sorted sequence cannot be determined.");
else if(flag == 2) printf("Inconsistency found after %d relations.\n", number);
else if(flag == 3)
printf("Sorted sequence determined after %d relations: %s.\n", number, ans);
}
return 0;
}
本文介绍了一种使用广度优先搜索(BFS)进行拓扑排序的方法,通过具体实例讲解了如何判断一组字母间的大小关系能否形成唯一的拓扑序列。文章详细展示了算法的实现过程,并附带完整的C++代码。
1068

被折叠的 条评论
为什么被折叠?



