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. Java Web学习总结(8)JSP(二)

    一,JSP中的九个内置对象 名称 类型 描述 out javax.servlet.jsp.JspWriter 用于页面输出 request javax.servlet.http.HttpServlet ...

  2. 4412 4路pwm输出

    一.4412 xpwmTOUT1 这是4412的GPD0_1路,itop中被使用为LCD的背光电路的pwm功能.因此如果使用教程中的代码,同样操作GPD0_1是行不通的. 会出现错误,所以需要解除在内 ...

  3. dumpsys, traceView调试命令

    1. dumpsys dumpsys cpuinfo: 打印cpu使用情况: dumpsys meminfo: 打印内存使用率情况: dumpsys activity: 打印所有活动的信息: dump ...

  4. R中unlist函数的使用

    买的书里面实例讲的不清不楚,所以看帮助文档了 用法:unlist(x, recursive = TRUE, use.names = TRUE) 帮助文档讲x可以是向量或者列表,如果是向量,则原样返回, ...

  5. bzoj 1026: [SCOI2009]windy数 & 数位DP算法笔记

    数位DP入门题之一 也是我所做的第一道数位DP题目 (其实很久以前就遇到过 感觉实现太难没写) 数位DP题目貌似多半是问从L到R内有多少个数满足某些限制条件 只要出题人不刻意去卡多一个$log$什么的 ...

  6. iOS图片压缩问题

    对于压缩的处理我给出的建议是 先判断 图片的大小,如果是本地图片最好用nsfilemanager 来判断 .如果不能用这个判断的话 就只能先将图片转成data,然后再判断了. 图片转成data 当然就 ...

  7. web测试点

    一.输入框 1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符“~!@#¥%……&*?[]{}”特别要注意单引号和&符号. 禁止直接输入特殊字符时, ...

  8. taintCheck的实现

    参考:http://bitblaze.cs.berkeley.edu/papers/taintcheck-full.pdf 1. 应用taint analysis需要解决三个问题 a. 哪些input ...

  9. 笔记大神推荐的个人知识文档管理工具mybase

    铛铛铛,今天我要给大家推荐一款个人知识笔记管理神器,不出你们所料,它就是mybase. 那mybase究竟能干啥呢?借用mybase中文官网的一句话来说,mybase软件可以将电脑上的文档.知识.笔记 ...

  10. Python3调用hessian

    领导派了个任务,实现服务器日志文件调用hessian接口保存到数据库 研究了半天python调用hessian的办法 首先使用hessian for python的链接: http://hessian ...