• 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
  • 相关阅读:
    学JAVA第十一天,属性与方法
    学JAVA第十天,一维数组及二维数组的使用。
    限制input[type=number]的输入位数策略整理
    淘宝NPM源的使用
    webpack之loader实践
    5月份开发问题整理
    前后端分离思考
    js 导航栏多项点击显示下拉菜单代码
    阵容首发
    jquery中的ajax请求到php(学生笔记)
  • 原文地址:https://www.cnblogs.com/de-compass/p/11748221.html
Copyright © 2020-2023  润新知