UESTC 1635 琵琶弦上说相思,当时明月在,曾照彩云归 拓扑排序、bfs

117 篇文章 2 订阅
6 篇文章 0 订阅

琵琶弦上说相思,当时明月在,曾照彩云归

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit  Status
给你n个仅由小写字母组成的字符串,请你找出一种字典序,使得这n个字符串在这种字典序下是从小到大排列的.


Input

第一行一个整数n(1≤n≤1000),表示有n个字符串.
接下来n行,每行一个字符串,每个字符串的长度不超过200,不含空串.


Output

如果无解,输出−1.
如果有解,输出一个长度为26的字符串,其中第ii个字母表示这种字典序下第ii小的字母.
如果有多个解,输出在字典序"abcdefghijklmnopqrstuvwxyz"下最小的那一个.


Sample input and output

Sample Input                 Sample Output
10                                            aghjlnopefikdmbcqrstuvwxyz
petr
egor
endagorion
feferivan
ilovetanyaromanova
kostka
dmitriyh
maratsnowbear
bredorjaguarturnik

cgyforever


Source

2017 UESTC Training for Graph Theory

UESTC 1635 琵琶弦上说相思,当时明月在,曾照彩云归


My Solution

题意:给出n个仅由小写字母组成的字符串,要求找出一种字典序,
使得这n个字符串在这种字典序下是从小到大排列的。

拓扑排序、bfs
对于相邻的2个字符串当第一次遇到不相等的字符是前一个u必定比比后一个v小,
所以可以u向v连一条有向边。
然后对于建出的这个图,跑一次拓扑排序即可。
时间复杂度 O(n*length)
空间复杂度 O(n*length)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> ii;
const int MAXN = 1e3 + 8;

char s[MAXN][208];
vector<int> sons[26];
priority_queue<ii, vector<ii>, greater<ii>> pq;
queue<int> q;
int deg[26];
bool flag[MAXN];
inline void bfs()
{
    int u, v, fa, sz, i;
    while(!pq.empty()){
        u = pq.top().first;
        fa = pq.top().second;
        pq.pop();
        q.push(u);
        flag[u] = true;
        sz = sons[u].size();
        for(i = 0; i < sz; i++){
            v = sons[u][i];
            if(v == fa) continue;
            deg[v]--;
            if(deg[v] == 0){
                pq.push(ii(v, u));
            }
        }
    }
}

int main()
{
    #ifdef LOCAL
    freopen("d.txt", "r", stdin);
    //freopen("d.out", "w", stdout);
    int T = 1;
    while(T--){
    #endif // LOCAL
    //ios::sync_with_stdio(false); cin.tie(0);

    int n, i, j, len1, len2;
    bool ans = true, f;
    //cin >> n;
    scanf("%d", &n);
    for(i = 0; i < n; i++){
        scanf("%s", s[i]);
    }
    for(i = 0; i < n - 1; i++){
        len1 = strlen(s[i]);
        len2 = strlen(s[i+1]);
        f = false;
        for(j = 0; j < min(len1, len2); j++){
            if(s[i][j] != s[i+1][j]){
                f = true;
                sons[s[i][j] - 'a'].push_back(s[i+1][j] - 'a');
                break;
            }
        }
        if(!f){
            if(len1 > len2){
                ans = false;
                break;
            }
        }
    }
    if(!ans) printf("-1\n");
    else{
        int sz;
        for(i = 0; i < 26; i++){
            sz = sons[i].size();
            for(j = 0; j < sz; j++){
                deg[sons[i][j]]++;
            }
        }
        for(i = 0; i < 26; i++){
            if(sons[i].size() && deg[i] == 0){
                pq.push(ii(i, -1));
            }
        }

        bfs();
        for(i = 0; i < 26; i++){
            if(deg[i] != 0){
                ans = false;
                break;
            }
        }
        if(!ans) printf("-1\n");
        else{
            i = 0;
            while(!q.empty()){
                while(flag[i]) i++;
                while(i < q.front()){
                    putchar(char('a' + i));
                    i++;
                    while(flag[i]) i++;
                }
                putchar(char('a' + q.front()));
                q.pop();
            }
            while(flag[i]) i++;
            while(i < 26){
                putchar(char('a' + i));
                i++;
                while(flag[i]) i++;
            }
        }
    }



    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}



  Thank you!

                                                                                                                                             ------from ProLights

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值