2019牛客暑期多校训练营(第五场)H subsequence 2【拓扑排序】
题意:
给你一个长度为n的隐藏字符串,由m个小写字符组成,接下来每一次会进行m*(m-1)/2次操作,给你两个不同的小写字符,以及把除这两个字符以外的字符删掉的字符串,以及他的长度,请问这个字符串是否存在,如果存在写出其中一种。
题目链接:
https://ac.nowcoder.com/acm/contest/885/H
题解:
拓扑排序基础练习题...对不起 我不会基础
我们可以给每个字符标记一个特定唯一的id,标记方式为 从左往右第几个某个字母
比如第14个b记录为 10014
bcbcbc
10001 20001 10002 20002 10003 20003
然后我们把子字符串相邻的字符建边,如果该图可以跑出拓扑排序就一定答案,且答案是拓扑排序
AC_code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5;
vector<int> vec[maxn*30];
int indeg[maxn*30],num[27],sum;
int main() {
int n, m;
cin >> n >> m;
int cnt = m * (m - 1) / 2;
while (cnt--) {
string op,t;
int len;
cin >> op>>len;
if(!len) {
getchar();
continue;
}
cin>>t;
int a=0,b=0,cur=0,id=0;
for (int i = 0; i < len; ++i) {
if(t[i]==op[0]) {
a++;
id=(t[i]-'a')*10000+a;
} else {
b++;
id=(t[i]-'a')*10000+b;
}
if(cur) {
indeg[id]++;
vec[cur].push_back(id);
}
cur=id;
}
num[op[0]-'a']=a;
num[op[1]-'a']=b;
}
queue<int> q;
for (int i = 0; i < 26; i++) {
if (num[i]&&indeg[i*10000+1] == 0) {
q.push(i*10000+1);
}
}
string ans;
while (!q.empty()) {
int top = q.front();
q.pop();
ans += (char)((top-1)/10000 + 'a');
for (auto v : vec[top]) {
indeg[v]--;
if (indeg[v] == 0) {
q.push(v);
}
}
}
if (ans.size() != n) {
cout << -1 << endl;
} else {
cout << ans << endl;
}
}