7-4 千手观音
思路
给定一个从小到大的顺序,通过这个顺序来得到每个位次的关系。
对于给定顺序有以下两种关系:
- 位数不同,不能得到关系
- 位数相同,通过进行比较,前n位(高位到低位),若在第n+1位出现不同,那么能够推出第n+1位的两个数的大小关系
因此我们可以依次来建立有向无环图,若a, b,则建立边<a, b>, 通过拓扑排序我们可以得到一个排序的大小关系,另外对于不能得出关系的可以进行字典序比较,所以我们在拓扑排序的时候应该用优先队列,小的string先进去,另一个需要注意的是,每个点的关系并不一定能得到,如果该字符串没有在字典里面,需要加进去(保证所有字符串都能够输出)
这个题有点卡常,不要使用#include <bit/stdc++.h>
, 能开优化的尽量优化,字典用unrodered_map
, 查询O(1)
Code
#include <queue>
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
using namespace std;
const int N = 1e5 + 10;
vector<vector<string>> v;
unordered_map<string, int> en;
bool f1;
unordered_map<string, vector<string>> g;
void bfs() {
priority_queue<string, vector<string>, greater<string>> q1;
for (auto &x: en) {
if (!x.second) {
q1.push(x.first);
}
}
while (q1.size()) {
string t = q1.top(); q1.pop();
if (f1 != false)
cout << ".";
else
f1 = true;
cout << t;
for (auto &x: g[t]) {
if (!--en[x]) {
q1.push(x);
}
}
}
}
int main() {
ios::sync_with_stdio(false);
int n; cin >> n;
auto act = [](vector<string> &a, vector<string> &b) {
if (a.size() != b.size()) return;
for (int i = 0; i < a.size(); i ++) {
if (a[i] == b[i]) continue;
g[a[i]].push_back(b[i]);
en[b[i]] ++;
break;
}
};
auto init = [](string &b) {
vector<string> t;
string s1;
for (int i = 0; i < b.size(); i ++) {
if (b[i] == '.') {
t.push_back(s1);
if (!en.count(s1)) en[s1] = 0;
s1.clear();
} else {
s1.push_back(b[i]);
}
}
if (s1.size()) {
if (!en.count(s1)) en[s1] = 0;
t.push_back(s1);
}
v.push_back(t);
};
for (int i = 1; i <= n; i ++) {
string t; cin >> t;
init(t);
if (i != 1) {
int k = v.size();
act(v[k - 2], v[k - 1]);
}
}
bfs();
}