Codeforces 875C National Property(拓扑排序)

题目链接  National Property

给定n个单词,字符集为m

现在我们可以把其中某些字母变成大写的。大写字母字典序大于小写字母。

问是否存在一种方案使得给定的n个单词字典序不下降。

首先判断是否存在相邻的两个单词,后一个是前一个的前缀。(两者不相等)

如果出现这种情况则直接输出无解。

建立起点s和终点t。每次扫描相邻的两个单词,找到他们第一个不相等的字母的位置。

和s相连的字母必须改成大写,和t相连的字母必须不能改成大写。

设前面那个单词的这个位置的字母为a, 后面的为b

如果a > b那么s到a之间连边,b到t之间连边(a一定要改成大写,b一定不能改成大写,否则就不成立了)

如果a < b那么b到a连一条有向边(如果a改成大写了那b更要改成大写了,因为这个关系的存在,b的字典序一定要大于a)

无解的判定:如果从s出发能走到t那么存在一个字母他必须改成大写也必须不能改成大写,矛盾。

最后把和s相连的那些字母都改成大写即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 1e5 + 10; int a[N], b[N];
int n, m;
int s, t, k, ret;
int vis[N];
vector <int> v[N];
vector <int> ans; void dfs(int x){
if (x == t){ puts("No"); exit(0);}
vis[x] = 1;
ans.push_back(x);
for (auto u : v[x]) if (!vis[u]) dfs(u);
} int main(){ scanf("%d%d", &n, &m);
s = m + 1, t = m + 2;
rep(i, 1, n){
scanf("%d", b);
rep(j, 1, b[0]) scanf("%d", b + j);
if (i == 1) rep(j, 0, b[0]) a[j] = b[j];
for (k = 1; k <= a[0] && k <= b[0] && a[k] == b[k]; ) ++k;
if (k <= a[0] && k > b[0]) return 0 * puts("No");
else if (k <= a[0] && k <= b[0]){
if (a[k] > b[k]){
v[s].push_back(a[k]);
v[b[k]].push_back(t);
}
else v[b[k]].push_back(a[k]);
}
rep(j, 0, b[0]) a[j] = b[j];
} dfs(s);
printf("Yes\n%d\n", (ret = ans.size()) - 1);
rep(i, 1, ret - 1) printf("%d ", ans[i]);
return 0 * putchar(10);
}
上一篇:Excel数据透视表


下一篇:node中glob模块