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;
    }
}
原文地址:https://www.cnblogs.com/wmj6/p/11305677.html