千手观音(天梯赛)

比赛的时候被前面的题目心态搞崩了 时间就不够了 就一个简单的拓扑排序 唉 真可惜了
首先对行字符串从前往后建边就好 对于上下两个具有相同前缀的字符串 首先必须两者大小相同
之后就对第一个不同的字符串建边就好
最后因为要字典序最小 用优先队列就好
#include <bits/stdc++.h>
using namespace std;
map<string, int> mp;
string S[10010];
vector<vector<string> > vs;
vector<string> ts;
int main() {
int n;
cin >> n;
string s;
int idx = 0;
for(int i = 0; i < n; ++ i) {
cin >> s;
s += ".";
string t = "";
ts.clear();
for(int j = 0; j < (int)s.size(); ++ j) {
if(s[j] == '.') {
ts.push_back(t);
if(!mp.count(t)) {
mp[t] = ++ idx;
S[idx] = t;
}
t = "";
}
else t += s[j];
}
vs.push_back(ts);
}
vector<vector<int> > G(idx + 1);
vector<int> d(idx + 1);
for(int i = 1; i < n; ++ i) {
if(vs[i].size() == vs[i - 1].size()) {
for(int j = 0; j < (int)vs[i].size(); ++ j) {
if(vs[i][j] != vs[i - 1][j]) {
int x = mp[vs[i - 1][j]], y = mp[vs[i][j]];
G[x].push_back(y);
d[y] ++;
break;
}
}
}
}
priority_queue<string, vector<string>, greater<string> > q;
int ok = 1;
for(int i = 1; i <= idx; ++ i)
if(d[i] == 0)
q.push(S[i]);
while(!q.empty()) {
string u = q.top();
if(ok) {
cout << u;
ok = 0;
}
else cout << "." << u;
q.pop();
for(int i=0;i<G[mp[u]].size();i++) {
int v=G[mp[u]][i];
d[v] --;
if(d[v] == 0) {
q.push(S[v]);
}
}
}
return 0;
}

浙公网安备 33010602011771号