zoukankan      html  css  js  c++  java
  • 2019牛客多校第五场H

    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
    ");
            return 0;
        }
        for(int i = 0; i < ans.size(); i++){
            printf("%c", ans[i]+'a');
        }
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    malloc
    排序算法学习笔记(三)-- 快速排序
    排序算法学习笔记(二)-- 归并排序
    排序算法学习笔记(一)-- 冒泡排序,选择排序,插入排序,希尔排序
    网络协议笔记
    域名和IP地址并用的理由
    WebSocket协议介绍
    Ajax概念
    共享密钥加密、公开密钥加密及HTTPS混合加密
    HTTP缺点
  • 原文地址:https://www.cnblogs.com/zhuyou/p/11285663.html
Copyright © 2011-2022 走看看