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. 【HDOJ6601】Keen On Everything But Triangle(主席树)

    题意:给定一个长为n的序列,有q次询问,每次询问[l,r]这段区间内挑三个数,能组成的三角形的最大周长,无解输出-1 n,q<=1e5,a[i]<=1e9 思路:题解写法和我的不太一样 先 ...

  2. JSP中获取客户端或浏览端信息的方式

    request应用:在JSP页面显示访问者IP  方式一:纯前台,不涉及后台操作.直接在jsp页面中需要显示IP的地方使用 代码:<%=request.getRemoteAddr()%> ...

  3. “pod repo push”遇到的2个问题的解决方案

    podspec文件push到遇到的第一个问题,将进行记录,主要是参考了下面大神的解决方案,主要是为了方便学习和记录 第一个问题: xcrun: error: invalid active develo ...

  4. 高并发之CAS机制和ABA问题

    什么是CAS机制 CAS是英文单词Compare and Swap的缩写,翻译过来就是比较并替换 CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B. 看如下几个例子: pac ...

  5. 用 Flask 来写个轻博客 (21) — 结合 reCAPTCHA 验证码实现用户注册与登录

    目录 目录 前文列表 扩展阅读 添加账户管理蓝图 新建控制器蓝图 新建表单 新建蓝图 main 的视图函数 新建模板 页面效果 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Fla ...

  6. opencv图像的基本操作3

    1.获取像素并修改 读取一副图像,根据像素的行和列的坐标获取它的像素值,对于RGB图像而言,返回RGB的值,对于灰度图则返回灰度值 import cv2 import numpy img = cv2. ...

  7. qt 如何使用 lamda 表达式接收线程中发射的数据,并在里面更新 UI ?

    Qt 信号和槽连接方式 常量 描述 Qt::AutoConnection (默认)如果接收方位于发出信号的线程中,则使用Qt::DirectConnection.否则,使用Qt::QueuedConn ...

  8. jQuery对于demo元素的上移、下移、删除操作等实现

    今天给大家分享一个实用的jQuery技能:dom元素的操作:我们经常会去获取dom元素去实现交互效果,以及数据的操作. 首先复习一下jQuery DOM 元素方法: .get() 获得由选择器指定的D ...

  9. windows下查看端口占用以及关闭相应的进程

    开始--运行--cmd 进入命令提示符 输入netstat -ano 即可看到所有连接的PID 之后在任务管理器中找到这个PID所对应的程序如果任务管理器中没有PID这一项,可以在任务管理器中选&qu ...

  10. python 图像的离散傅立叶变换

    图像(MxN)的二维离散傅立叶变换可以将图像由空间域变换到频域中去,空间域中用x,y来表示空间坐标,频域由u,v来表示频率,二维离散傅立叶变换的公式如下: 在python中,numpy库的fft模块有 ...