zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第五场)H.subsequence 2(拓扑)

    题意:给你一个字符串的长度n 现在询问了m*(m-1)/2次 每次都可以询问两个字符 然后 会告诉你只留下这两个字符后 字符串的样子 现在问你能不能还原字符串 如果能就输出字符串 否则输出-1

    思路:我们可以发现每次返回的字符串都有明显的拓扑关系 所以我们每次都进行前后连边 然后就是对于同一个字符 我们需要进行编号 最后还有一些细节判断

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 3e5+7;
    const int inf = 0x3f3f3f3f;
    typedef long long ll;
    const ll mod = 1e7+9;
    int n,m;
    int num[30],ru[N],vis[N];
    vector<int> G[N];
    int no=1e4;
    vector<char> s;
    bool top(){
        queue<int> q;
        int gg=0; int xx=0;
        for(int i=0;i<m;i++){
            gg+=num[i];
            if(!num[i]) xx++;
            for(int j=1;j<=num[i];j++)
                if(!ru[j+i*no]&&!vis[j+i*no]){
                    q.push(j+i*no);
                    vis[j+i*no]=1;
                }
        }
        int res=0;
        while(!q.empty()){
            int tmp=q.front();
            q.pop();
            res++;
            s.push_back(char(tmp/no+'a'));
            for(int i=0;i<G[tmp].size();i++){
                ru[G[tmp][i]]--;
                if(!ru[G[tmp][i]]&&!vis[G[tmp][i]]){
                        q.push(G[tmp][i]);
                        vis[G[tmp][i]]=1;
                    }
            }
        }
        if(gg!=res) return false;
        int len=s.size();
        if(len==n) return true;
        else if(len<n){
            if(len+xx<=n){
                for(int i=0;i<m;i++)
                    if(!num[i])
                        s.push_back(char(i+'a'));
                len=len+xx;
                while(len<n){
                    s.push_back(char('a'));
                    len++;
                }
            }else{
                return false;
            }
        }else return false;
    }
    int main(){
        //ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cin>>n>>m;
        for(int i=1;i<=m*(m-1)/2;i++){
            char a,b; cin>>a>>b;
            int len; cin>>len;
            getchar();
            string s; getline(cin,s);
            if(!num[a-'a'])
                for(int j=0;j<len;j++)
                    if(s[j]==a)
                        num[a-'a']++;
            if(!num[b-'a'])
                for(int j=0;j<len;j++)
                    if(s[j]==b)
                        num[b-'a']++;
            int cnt[20]={0};
            for(int j=0;j<len-1;j++){
                int x,y;
                if(j==0) cnt[s[j]-'a']++;
                x=cnt[s[j]-'a'];
                cnt[s[j+1]-'a']++;
                y=cnt[s[j+1]-'a'];
                G[x+(s[j]-'a')*no].push_back(y+(s[j+1]-'a')*no);
                ru[y+(s[j+1]-'a')*no]++;
            }          
        }
        if(top()){
            for(int i=0;i<s.size();i++)
                cout<<s[i];
            cout<<endl;
        }else{
            cout<<"-1"<<endl;
        }
    }
  • 相关阅读:
    HDU 6166
    codeforces 798D Mike and distribution
    Codeforces Round #409 (Div. 2) D Volatile Kite
    Codeforces Round #409 (Div. 2) C Voltage Keepsake(二分)
    HDU 4609 3-idiots(FFT计数)
    LightOJ 1236 Pairs Forming LCM(算术基本定理)
    HDU 1540 Tunnel Warfare(线段树,单点更新,区间查询)
    创建最简单的Struts2项目
    java自定义拦截器
    java拦截器和过滤器的区别
  • 原文地址:https://www.cnblogs.com/wmj6/p/11305677.html
Copyright © 2011-2022 走看看