#include<bits/stdc++.h> usingnamespace std; //"O campeão tem nome, e se chama Charles Oliveira!" #define int long long #define endl '\n' #define ep emplace #define pob #define ll long long #define pb push_back #define pof pop_front #define pob pop_back #define all(a) a.begin(),a.end() #define rall(a) a.rbegin(),a.rend() #define mod 998244353 #define MOD 1000000007 #define N 200010 #define INF 1e18
using ld = longdouble; using ui = unsigned; using ull = unsignedlonglong; using i128 = __int128;
intcheck_topo(int n, const vector<vector<int>>& adj, string& res){ vector<int> in_degree(n, 0);//这里的in_degree里,开始全都初始化为0了 //所以就算是语句中只出现了 A和B,比如说A<B的化,那么A和C都会被输入到q中去 for (int u = 0; u < n; u++) { for (int v : adj[u]) in_degree[v]++; } //每次都要从头统计一次,防止新的命令出现产生了环 queue<int> q; for (int i = 0; i < n; i++) { if (in_degree[i] == 0) q.push(i); }
bool is_undetermined = false; res = ""; int count = 0; while (!q.empty()) { // 关键点:如果队列中超过一个元素,说明有多个起点,顺序不唯一 //比如是3个点ABC,但是只有一条命令A<B,这个时候我们的队列中就只有A和C,这个时候的size就是大于1的 if (q.size() > 1) is_undetermined = true;
int u = q.front(); q.pop(); count++; res += (char)('A' + u);
for (int v : adj[u]) { if (--in_degree[v] == 0) { q.push(v); } } }
// 如果处理的节点数少于 n,说明图中存在环 //不管是只执行了一条语句还是执行了好多条语句,只要没有环的出现,就是count==n的 if (count < n) return0; // 如果虽然处理完了 n 个点,但中间出现过分支 if (is_undetermined) return2; // 否则,唯一序 return1; }
voidsolve(){ int n, m; while (cin >> n >> m && (n || m)) { vector<vector<int>> adj(n); bool finished = false; string res;
for (int i = 1; i <= m; i++) { string s; cin >> s; if (finished) continue;
int u = s[0] - 'A'; int v = s[2] - 'A'; adj[u].push_back(v);
int status = check_topo(n, adj, res);
if (status == 0) { printf("Inconsistency found after %d relations.\n", i); finished = true; } elseif (status == 1) { cout << "Sorted sequence determined after " << i << " relations: " << res << "." << endl; finished = true; } }
if (!finished) { printf("Sorted sequence cannot be determined.\n"); } } } signedmain(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int t=1; //cin>>t; while(t--)solve(); }
分析
简单来说就是,给你几个字符串,类似这样的
1 2 3 4 5 6 7 8
4 6 A<B A<C B<C C<D B<D A<B
要你分析,这个构成的这个关系是不是合法的/违法的/不明确的 如果有着合理的A
1 2
26 1 A<Z
是这样要有26个字母之间的关系,但是命令行不够的话,那就是不明确的 很容易想到拓扑排序
topo函数
因为我们在每一个字符串被传入进来的时候,都要检查一次,所以我们的拓扑函数传入的参数是要带我们建表的数组的 int check_topo(int n, const vector>& adj, string& res),就是这个adj
1 2 3
for (int u = 0; u < n; u++) { for (int v : adj[u]) in_degree[v]++; }