站外拓扑排序题求助
  • 板块学术版
  • 楼主yyz1005
  • 当前回复0
  • 已保存回复0
  • 发布时间2022/3/21 18:31
  • 上次更新2023/10/28 06:00:15
查看原帖
站外拓扑排序题求助
220824
yyz1005楼主2022/3/21 18:31

[题目描述]

有一天,小y突然发现自己的计算机感染了一种病毒!还好,小y发现这种病毒很弱,只是会把文档中的所有字母替换成其它字母,但并不改变顺序,也不会增加和删除字母。

现在怎么恢复原来的文档呢!小y很聪明,他在其他没有感染病毒的机器上,生成了一个由若干单词构成的字典,字典中的单词是按照字母顺序排列的,他把这个文件拷贝到自己的机器里,故意让它感染上病毒,他想利用这个字典文件原来的有序性,找到病毒替换字母的规律,再用来恢复其它文档。

现在你的任务是:告诉你被病毒感染了的字典,要你恢复一个字母串。

输入

第一行是一个正整数K(≤50000),表示字典中的单词个数,以下K行,是被病毒感染了的字典,每行一个单词,最后一行是需要你恢复的一串字母。所有字母均为小写。

输出

一行,为恢复后的一串字母。当然也有可能出现字典不完整、甚至字典是错的情况,这时请输出一个0。

样例输入

6
cebdbac
cac
ecd
dca
aba
bac
cedab

样例输出

abcde

我的代码

#include<bits/stdc++.h>
using namespace std;
int n;
int turn[30];//word->number
char retu[30];//number->word
int tot = 0;
char s[50010][110];
int len[500010];
char fact[30];
struct Edge{
    int from,to,next;
} edge[500010];
int head[30],cnt = 0,in[30];
void add(int u,int v){
    cnt++;
    edge[cnt].from = u;
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
    in[v]++;
}
void cal(int x){
    for(int j = 0; j < len[x-1]; j++){
        if(s[x-1][j]!=s[x][j]){
            //printf("%c(%d)-%c(%d)\n",s[x-1][j],turn[s[x-1][j]-'a'+1],s[x][j],turn[s[x][j]-'a'+1]);
            add(turn[s[x-1][j]-'a'+1],turn[s[x][j]-'a'+1]);
            break;
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        scanf("%s", s[i]);
        len[i] = strlen(s[i]);
        for(int j = 0; j < len[i]; j++){
            if(turn[s[i][j]-'a'+1]==0){
                tot++;
                turn[s[i][j]-'a'+1] = tot;
                retu[tot] = s[i][j];
            }
        }
    }
    for(int i = 2; i <= n; i++) cal(i);
    queue<int> q;
    for(int i = 1; i <= tot; i++){
        if(in[i]==0) q.push(i);
    }
    //for(int i = 1; i <= 26; i++) printf("%d %d\n",turn[i],retu[i]);
    if(q.empty()||q.size()>1) printf("0");
    else {
        int ans[30],p = 0;
        while(!q.empty()){
            int v = q.front();
            q.pop();
            //if(!q.empty()){
            //  printf("0");
            //  return 0;
            //}
            p++;
            ans[p] = v;
            int coun = 0;
            for(int i = head[v]; i; i = edge[i].next){
                in[edge[i].to]--;
                if(in[edge[i].to]==0){q.push(edge[i].to);coun++;}
            }
            if(coun>1){
               printf("0");
               return 0;
            }
        }
        if(p!=tot) printf("0");
        else {
            for(int i = 1,j = 1; i <= p; j++){
                if(turn[j]!=0){
                    fact[retu[ans[i]]-'a'+1] = retu[turn[j]];
                    i++;
                }
            }
            char sol[110];
            scanf("%s", sol);
            int length = strlen(sol);
            for(int i = 0; i < length; i++){
                sol[i] = fact[sol[i]-'a'+1];
            }
            printf("%s", sol);
            //for(int i = 1; i <= 26; i++){
            //  printf("%c-%c\n",i+'a'-1,fact[i]);
            //}
        }
    }
    return 0;
}

建立了字母与数字的关系后拓扑排序,但是一直只有 67pts,不知道哪里错了

2022/3/21 18:31
加载中...