Codeforces Round #290 (Div. 2), problem: (C) Fox And Names 【BFS+无前驱的顶点优先+拓扑排序】

题意

有N个字符串,要求你给出一个字典序,使它们按字典序排序后的结果和输入顺序一样。

思路

显然对于一个字符串i优先于字符串j,i的第一个和j不同的字母优于j的对应的字母。(若找不到该字母,即i是j的前面一部分则可以直接判断无解)

那么我们可以得到很多对字母之间的优先顺序,要给出26个字母的优先顺序,无非就是拓扑排序。

采用无前驱的顶点优先BFS的拓扑排序,如果存在没有被拓扑排序所排序到的节点,那么无解(即有环)。

发现没有特殊情况。

因为点少,用邻接矩阵建图。

code

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=110;
int n;
queue<int>q;
char s[maxn][maxn],ans[maxn];
bool link[30][30];
int in[maxn];
//无前驱的顶点优先bfs
bool bfs(){
    int cnt=0;
    for(int i=0;i<26;i++){
        if(in[i]==0){ //先将入度为0的结点入队列
            q.push(i);
            ans[cnt++]='a'+i;
        }
    }
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(link[now][i]){
                in[i]--;
                if(in[i]==0){
                    q.push(i);
                    ans[cnt++]='a'+i;
                }
            }
        }
    }
    ans[26]='\0';
    if(cnt<26) return false;
    else return true;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>s[i];
    bool flag=false;
    for(int i=0;i<n-1;i++){
        int len1=strlen(s[i]),len2=strlen(s[i+1]);
        int ok=0;    
        for(int j=0;j<len1&&j<len2;j++){
                if(s[i][j]!=s[i+1][j]){
                    ok=1;
                    int u=s[i][j]-'a',v=s[i+1][j]-'a';
                    if(!link[u][v]){
                        link[u][v]=true;
                        in[v]++;
                    }
                }
                if(ok) break;
        }
        if(!ok&&len1>len2) flag=true; //判断是否满足字典序
        if(flag) break;
    }
    if(flag)
        cout<<"Impossible"<<endl;
    else{
        if(bfs())
            cout<<ans<<endl;
        else
            cout<<"Impossible"<<endl;
    }
    return 0;
}
学如逆水行舟,不进则退
发布了410 篇原创文章 · 获赞 959 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/weixin_42429718/article/details/104100586
今日推荐