H - subsequence 2

题意

要你使用前\(m\)个小写字母构造一个长度为\(n\)的字符串

有\(m*(m-1)/2\)个限制条件:

  • \(c_{1} 、c_{2}、 len\):表示除去其他非\(c_{1}、c_{2}\)之外的字母剩下的串长度为\(len\)
  • \(s\):除去其他非\(c_{1}、c_{2}\)之外的字母剩下的字符串,长度为\(len\)

需要我们根据这个限制条件构造出原串,如果不存在输出\(-1\)

思路

我们可以发现题目给了两个字母之间的相对位置。比如\(aab\),第二个\(a\)前面一定得接了个\(a\),\(b\)一定要第二个\(a\)的条件符合之后,然后第二个\(a\)放进去之后才能到\(b\)

那么对于每个字母都要先把前面的都输出完了,才能到自己,那么我们可以想到拓扑(其实是队友想的),一定要入度为零才能到本身,然后我们就可以和拓扑结合起来。

  • 定义字母:我们可以令\(a\)为\(0000\)~\(9999\)之间的数来定义(因为最多可能有\(1e^4\)个), 然后\(b\)用\(10000\)~\(19999\)这样接下去定义每个字母。
  • 建图:根据题目给的串建图, 前后建一条边。
  • 然后去跑拓扑就\(OK\)了
  • 如果你构造出来的串长度不为\(n\)就输出\(-1\)(出现循环节之类乱七八糟的情况)

一些坑点

  • 建图的时候要判断会不会出现前面出现的\(a\)有\(3\)个,这次出现的\(a\)有\(4\)个这样的情况,这样不符合条件,可以加一个数组特判一下。
  • 输入要注意\(len = 0\)的时候会输入空行,这边要处理好。(没处理好的我,\(WA\)了好多发)

一些数据

这些数据都是输出\(-1\),其实我第一组数据之前只是输入出锅了,然后导致我一直\(WA\),其实我没有输出\(-1\)也过了

3 3
ab 3
aab
ac 2
aa
bc 0 3 3
ab 3
aab
ac 1
a
bc 1
b

AC 代码

(本人太菜,代码很乱,请多见谅)

#include<bits/stdc++.h>
#define mes(a, b) memset(a, b, sizeof a)
using namespace std;
const int maxn = 1e4+10;
int n, m;
int head[maxn*50], f[30], cnt, in[maxn*50], sum[30];
char ch[maxn];
vector<int> ans;
struct Edge{
int v, next;
}e[maxn*50]; void init(){ //初始化
mes(head, -1);
mes(in, 0);
mes(sum, 0);
for(int i = 0; i <= 26; i++){
f[i] = i*10000;
}
ans.clear();
cnt = 0;
} void add(int u, int v){
e[++cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt;
} int change(int u){ //根据字母的ID转换为字母
for(int i = 0; i < 26; i++){
if(u - f[i] < 10000)
return i;
}
} int topu(){
queue<int> q;
int tot = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < sum[i]; j++){
if(!in[j+f[i]]){
q.push(j+f[i]);
}
}
}
while(!q.empty()){
int u = q.front(); q.pop();
if(change(u) >= m)
return -1;
ans.push_back(change(u));
tot++;
for(int i = head[u]; ~i; i = e[i].next){
int v = e[i].v;
in[v]--;
if(!in[v])
q.push(v);
}
}
return tot;
} int main(){
scanf("%d%d", &n, &m);
init();
int q = m*(m-1)/2;
char c1, c2;
int len;
int flag = 0;
while(q--){
char s[10];
scanf("%s%d", s, &len);
c1 = s[0];c2 = s[1];
getchar();
gets(ch);
int cnt1 = 0, cnt2 = 0, u, v; //cnt1:c1字母出现的次数
if(len > 0){ //cnt2:c2字母出现的次数
if(ch[0] == c1){
u = cnt1+f[c1-'a'];
cnt1++;
}
else{
u = cnt2+f[c2-'a'];
cnt2++;
}
for(int i = 1; i < len; i++){
if(ch[i] == c1){
v = cnt1+f[c1-'a'];
cnt1++;
}
else{
v = cnt2+f[c2-'a'];
cnt2++;
}
add(u, v);
u = v;
in[v]++;
}
}
if(!sum[c1-'a']|| sum[c1-'a'] == cnt1) //如果这次出现的次数和之前不一样,不符合条件
sum[c1-'a'] = cnt1;
else
flag = 1;
if(!sum[c2-'a']|| sum[c2-'a'] == cnt2)
sum[c2-'a'] = cnt2;
else
flag = 1;
}
int num = topu();
if(num != n || flag){
printf("-1\n");
return 0;
}
for(int i = 0; i < ans.size(); i++){
printf("%c", ans[i]+'a');
}
printf("\n");
return 0;
}

2019牛客多校第五场H - subsequence 2 拓扑的更多相关文章

  1. 牛客多校第五场 H subsequence 2 拓扑排序

    题意: 给你长度最长为1000的字符串,这个字符串中最多有10种字母,每次给你两种字母,输出这两种字母在字符串中的相对位置,问你这个字符串原本是什么样子,如果不存在则输出-1 题解: 把整个字符串看作 ...

  2. 2019牛客多校第五场 G subsequence 1 dp+组合数学

    subsequence 1 题意 给出两个数字串s,t,求s的子序列中在数值上大于t串的数量 分析 数字大于另一个数字,要么位数多,要么位数相同,字典序大,位数多可以很方便地用组合数学来解决,所以只剩 ...

  3. 2019牛客多校第五场 generator 1——广义斐波那契循环节&&矩阵快速幂

    理论部分 二次剩余 在数论中,整数 $X$ 对整数 $p$ 的二次剩余是指 $X^2$ 除以 $p$ 的余数. 当存在某个 $X$,使得式子 $X^2 \equiv d(mod \ p)$ 成立时,称 ...

  4. 2019牛客多校第五场generator2——BSGS&&手写Hash

    题目 几乎原题 BZOJ3122题解 分析 先推一波公式,然后除去特殊情况分类讨论,剩下就是形如 $a^i \equiv b(mod \ p)$ 的方程,可以使用BSGS算法. 在标准的BSGS中,内 ...

  5. 2019牛客多校第五场F maximum clique 1 最大独立集

    题意:给你n个数,现在让你选择一个数目最大的集合,使得集合中任意两个数的二进制表示至少有两位不同,问这个集合最大是多大?并且输出具体方案.保证n个数互不相同. 思路:容易发现,如果两个数不能同时在集合 ...

  6. 2019牛客多校第五场G-subsequence 1 DP

    G-subsequence 1 题意 给你两个字符串\(s.t\),问\(s\)中有多少个子序列能大于\(t\). 思路 令\(len1\)为\(s\)的子序列的长度,\(lent\)为\(t\)的长 ...

  7. 2019牛客多校第五场 B - generator 1 矩阵快速幂+十倍增+二进制倍增优化

    B - generator 1 题意 给你\(x_{0}.x_{1}.a.b.b.mod\),根据\(x_{i} = a*x_{i-1} + b*x_{i-2}\)求出\(x_{n}\) 思路 一般看 ...

  8. 2019牛客多校第五场B-generator 1(矩阵快速幂)

    generator 1 题目传送门 解题思路 矩阵快速幂.只是平时的矩阵快速幂是二进制的,这题要用十进制的快速幂. 代码如下 #include <bits/stdc++.h> #defin ...

  9. 2019 牛客多校第五场 B generator 1

    题目链接:https://ac.nowcoder.com/acm/contest/885/B 题目大意 略. 分析 十进制矩阵快速幂. 代码如下 #include <bits/stdc++.h& ...

随机推荐

  1. 【Linux】【Kibana】解决Kibana启动失败:Data too large问题

    今天重启Kibana容器,结果启动不了,一看日志发现是Data数据量太大报错. FATAL [circuit_breaking_exception] [parent] Data too large, ...

  2. delphi WaitForSingleObject 示例之一等待另一个进程的结束

    <pre>unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Cont ...

  3. windows系统的安装时间怎么查看

    方法一:利用命令符窗口查询 直接按下Windows+R组合键  出现运行对话框(或 点击开始—运行),输入cmd,进入命令符窗口 然后,在该界面下输入”systeminfo”,然后回车,等待系统自动运 ...

  4. shell脚本——注释(单行注释 多行注释)

    参考 : https://blog.csdn.net/weixin_42167759/article/details/80703570 单行注释 以"#"开头的行就是注释,会被解释 ...

  5. UITableView 支持左右滑动(一)

    原理如下: SwipeTableView subView 1 :  UIScrollView作为容器, 主要负责左右滑动, 每个tableView的顶部设置相同的contentInset subVie ...

  6. Asp.Net Core 第04局:依赖注入

    总目录 前言 本文介绍Asp.Net Core中默认的依赖注入(DI)模式. 环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 开局 第一手:依赖注入说明 1.一个 ...

  7. python- ' % '运算符的用途(非常重要)

    %运算符就是用来格式化字符串的. 在字符串内部, %s表示用字符串替换, %d表示用整数替换, 有几个%?占位符,后面就跟几个变量或者值,顺序要对应好. 如果只有一个%?,括号可以省略. 另一种格式化 ...

  8. 重定向和转向的写法,重定向以post方式提交

    重转向保留跳转过来的Referer,路径不会变1 request.getRequestDispatcher("/eventweb/index.sp?loginId=" + logi ...

  9. 多线性方程组迭代算法——Jacobi迭代算法的Python实现

    多线性方程(张量)组迭代算法的原理请看这里:若想看原理部分请留言,不方便公开分享 Gauss-Seidel迭代算法:多线性方程组迭代算法——Gauss-Seidel迭代算法的Python实现 impo ...

  10. 模拟javaWeb责任链的设计

    这篇文章介绍了责任链模式的应用:本文介绍如果自己实现一个责任链 定义请求和响应信息 简单定义请求类Request(封装一个字符串) public class Request { String requ ...