• cqyz oj | 罕见的秩序 | 拓扑排序


    Description

      一个珍稀书籍的收藏家最近发现了一本用陌生的语言写的一本书,这种语言采用和英语一样的字母。这本书有简单的索引,但在索引中的条目的次序不同于根据英语字母表给出的字典排序的次序。这位收藏家试图通过索引来确定这个古怪的字母表的字符的次序,(即对索引条目组成的序列进行整理),但因为任务冗长而乏味,就放弃了。
      请编写程序完成这位收藏家的任务,程序输入一个按特定的序列排序的字符串集合,确定字符的序列是什么。

    Input

      输入是由大写字母组成的字符串的有序列表,每行一个字符串。每个字符串最多包含20个字符。该列表的结束标志是一个单一字符’#’的一行。并不是所有的字母都被用到,但该列表蕴涵对于被采用的那些字母存在着一个完全的次序。

    Output

      输出可能存在三种情况:如果不能得到一个完全次序,则输出none;如果次序不唯一,则输出 non-unique;如果能唯一确定,则输出字母的排列次序。

    Sample Input 1

    XWY
    ZX
    ZXY
    ZXW
    YWWX
    #

    Sample Output 1

    XZYW

    Hint

    字符串数目最多不超过5000个。

     
    建图时只需要比较相邻的两个字串来获得字母大小关系,因为两两相互比较的大小关系可以用相邻比较的结果来得到
    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    typedef long long ll;
    using namespace std;
    const int maxn = 30, maxm = 5005, inf = 0x3f3f3f3f;
    
    int fir[maxn], to[maxm], ne[maxm], np;
    void add(int x, int y) {
        ne[++np] = fir[x];
        fir[x] = np;
        to[np] = y;
    }
    
    char w[maxm][maxn];
    int cnt;
    void data_in() {
        char tmp[maxn];
        cnt = 0;
        while(true) {
            scanf("%s", tmp);
            if(tmp[0] == '#') break;
            strcpy(w[++cnt], tmp);
        }
    }
    
    int n;
    int rd[maxn];
    int mark[maxn], ha[maxn][maxn];
    vector<int> topo;
    int toposort() {
        int ret = 1;
        queue<int> Q;
        for(int i=0; i<26; i++)
            if(mark[i] && !rd[i]) Q.push(i);
        while(!Q.empty()) {
            if(Q.size()>=2) ret = 2;
            int u = Q.front(); Q.pop();
            topo.push_back(u);
            for(int i=fir[u]; i; i=ne[i]) {
                int v = to[i];
                if(!--rd[v]) Q.push(v);
            }
        }
        if(topo.size() < n) ret = 0;
        return ret;
    }
    
    void sett() {
        for(int i=2; i<=cnt; i++) {
            int j = i-1, k = 0;
            while(w[i][k] && w[j][k]) {
                if(w[i][k] != w[j][k]) break;
                k++;
            }
            
            if(w[i][k] && w[j][k]){
                int x = w[i][k] - 'A', y = w[j][k] - 'A';
                if(ha[x][y]) continue;
                ha[x][y] = 1;
                add(x, y); rd[y]++;
                mark[x]++; mark[y]++;
            }
        }
        
        n = 0;
        for(int i=0; i<26; i++)
            if(mark[i]) n++;
    }
    
    void solve() {
        sett();
        int ok = toposort();
        if(ok == 0) puts("none");
        else if(ok == 2) puts("non-unique");
        else
            for(int i = topo.size()-1; i>=0; i--)
                putchar(topo[i]+'A');
    }
    
    int main() {
        data_in();
        solve();
        return 0;
    }
    /*
    XWY
    ZX
    ZXY
    ZXW
    YWWX
    #
    
    */
    View Code
  • 相关阅读:
    Linux系统运维之MYSQL数据库集群部署(主从复制)
    Linux系统运维之负载均衡Tengine
    Linux系统运维之subversionEdge部署
    Linux系统运维之Hadoop、Hive、Flume数据处理
    CoIDE在STM32系列单片机中的使用实践
    软硬件调试九法:第三条规则 不要想而要看
    《产品经理》读书笔记
    <读书笔记> 代码整洁之道
    关于鼠标手的症状和恢复方法
    <读书笔记>软件调试之道 :从大局看调试-理想的调试环境
  • 原文地址:https://www.cnblogs.com/de-compass/p/11748221.html
Copyright © 2020-2023  润新知