题目链接
题解
题意
找出拓扑排序。
注意题目给的三种特殊情况。
思路
题目给出的是小于关系,可以看作边。
看一下题目给的范围并不是特别大,可以来一个边judge一次。
- 碰到环则立即输出;
- 判断已输入的节点数量与总节点数量是否相等,不相等则继续判断,相等则输出已确定。
注意一下重复边,可以直接跳过,否则注意不要重复记录入度。
注意一下输出格式,不要漏了某个点QAQ
AC代码
#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(A, tree) memcpy(A, tree, sizeof(tree))
#define eps (1e-8)
#define PI (acos(-1.0))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;
int const N = 30;
int e[N][N];
int in[N], tmp[N];
int n, m;
char ch[4];
set<int> st;
bool vis[N];
vector<int> ans;
int topological() {
queue<int> q;
int cnt = 0;
ans.clear();
copy(begin(in), end(in), begin(tmp));
for (int i = 1; i <= n; i++) {
if (tmp[i] == 0 && st.find(i) != st.end()) {
q.push(i);
vis[i] = true;
}
}
mms(vis, false);
bool flag = true;
while (!q.empty()) {
int x = q.front();
q.pop();
cnt += 1;
ans.push_back(x);
int num = 0;
for (int y = 1; y <= 26; y++) {
if (e[x][y] == 1) {
tmp[y] -= 1;
if (tmp[y] == 0 && !vis[y]) {
num += 1;
if (num > 1) flag = false;
q.push(y);
vis[y] = true;
}
}
}
}
if (cnt < st.size()) return -1;
else if (cnt == n && flag) return 1;
return 0; // 没有必要,至少不写有点不舒服QAQ
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%s", ch);
int x = ch[0] - 'A' + 1;
int y = ch[2] - 'A' + 1;
st.insert(x);
st.insert(y);
if (e[x][y] == 1) continue;
e[x][y] = 1;
in[y] += 1;
int ret = topological();
if (ret == -1) {
printf("Inconsistency found after %d relations.", i);
return 0;
} else if (ret == 1) {
printf("Sorted sequence determined after %d relations: ", i);
for (auto item : ans) printf("%c", 'A' + item - 1);
printf(".");
return 0;
}
}
printf("Sorted sequence cannot be determined.");
return 0;
}