题目链接
每加入一个条件就要进行一次拓扑排序
有以下三种情况:
- 条件不足:多个入度为0、多个出度为0、当前能得出的序列长度小于总字母数量
- 出现环路
- 成功判断
测试点1
4 6
C<D
C<B
B<A
C<D
D<A
A<A
Inconsistency found after 6 relations.
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#include <set>
using namespace std;
const int N = 30;
struct node {
int a, b;
}e[610]; //保存m个条件
int d[N], out[N]; //入度 出度
int n, m, curnum; //curnum表示当前出现的字母数量
string ans; //最后输出的序列
bool vis[N]; //标记字母是否被输入过
vector<set<int>> v(N); //存储每个点指向的点
int topo() {
queue<int> q;
int myd[N], res = 0; //res标记是否是条件不足的情况 myd用来复制d,避免操作影响全局入度数组
int cnt1 = 0, cnt2 = 0;
for (int i = 0; i < n; i++) myd[i] = d[i];
for (int i = 0; i < n; i++) {
if (myd[i] == 0 && vis[i]) {
q.push(i);
cnt2++;
}
if (out[i] == 0 && vis[i]) cnt1++;
}
if (cnt1 > 1 || cnt2 > 1) res = 1;
while (q.size()) {
int t = q.front();
q.pop();
ans += char(t + 'A');
cnt1 = 0;
for (const auto& x : v[t]) {
if (--myd[x] == 0) {
if (++cnt1 > 1) {
res = 1;
}
q.push(x);
}
}
}
// 2 成立
// 1 矛盾
// 0 不足
if (ans.size() < curnum) return 1;
else if (res == 1 || (ans.size() == curnum && curnum < n)) return 0;
return 2;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
cin >> n >> m;
memset(d, 0, sizeof d);
for (int i = 1; i <= m; i++) {
char a, b, c;
cin >> a >> b >> c;
e[i].a = a - 'A';
e[i].b = c - 'A';
}
for (int i = 1; i <= m; i++) {
int num1 = e[i].a, num2 = e[i].b;
if (v[num1].find(num2) == v[num1].end()) { //给出的条件没出现过
d[num2]++;
out[num1]++;
v[num1].insert(num2);
}
if (!vis[num1]) { //标记字母出现
vis[num1] = 1;
curnum++; 当前总字母数加1
}
if (!vis[num2]) {
vis[num2] = 1;
curnum++;
}
ans = "";
int x = topo();
if (x == 2) {
printf("Sorted sequence determined after %d relations: %s.\n", i, ans.c_str());
return 0;
} else if (x == 1) {
printf("Inconsistency found after %d relations.\n", i);
return 0;
}
}
printf("Sorted sequence cannot be determined.");
return 0;
}