Codeforces 510C

CodeForces 510C

题意:给出n个名字,问是否存在一个字典序(这个字典序是任意的)使得这些名字是按这个字典序输出的,如果存在输出任意一个可行的字典序

思路:拓扑排序,关键是建图,第i个和i+1个建一条由i指向i+1的单向边,建图是a-z26个字母间建图,每2个相邻的单词之间排序的依据是第一个不相同的字母,由这个不相同的字母之间建边,如果没有不相同的则不建边,这里有一个坑,就是 aaa aaaa这种数据,要特判

AC代码:

#include "iostream"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define ll long long
#define endl ("\n")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ft (frist)
#define sd (second)
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const long long INF = 1e18+1LL;
const int inf = 1e9+1e8;
const int N=1e5+100;
const ll mod=1e9+7;

struct AN{
    int id,num;
    bool friend operator< (AN a, AN b){
        return a.num<b.num;
    }
}ans[160];
char s[155][155];
int n,head[155],nex[305],to[305],tot=1,in[300],cnt;
bool vis[155];
void add(int u, int v){
    to[tot]=v;
    nex[tot]=head[u];
    head[u]=tot++;
}

void topu(int u){
    queue<int> Q;
    while(!Q.empty()) Q.pop();
    Q.push(u);
    vis[u]=1;
    while(!Q.empty()){
        int now=Q.front(); Q.pop();
        ans[now].num=++cnt;
        for(int i=head[now]; i!=-1; i=nex[i]){
            int v=to[i]; in[v]--;
            if(in[v]==0 && vis[v]==0){
                Q.push(v);
                vis[v]=1;
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n;
    mem(head,-1);
    for(int _=1; _<=n; ++_){
        cin>>s[_];
    }
    for(int i=1; i<n; ++i){
        int k=0;
        int l1=strlen(s[i]), l2=strlen(s[i+1]);
        while(s[i][k]==s[i+1][k] && k<=l1 && k<=l2){
            ++k;
        }
        if(k>=l1 || k>=l2){
            if(l2<l1){
                cout<<"Impossible\n";
                return 0;
            }
            continue;
        }
        add(s[i][k]-‘a‘+1, s[i+1][k]-‘a‘+1);
        in[s[i+1][k]-‘a‘+1]++;
    }
    for(int i=1; i<=26; ++i){ //cout<<in[i]<<" ";
        if(in[i]==0 && vis[i]==0) topu(i);//bug(ans[i].num)
    }
    for(int i=1; i<=26; ++i){
        if(ans[i].num==0){
            cout<<"Impossible\n";
            return 0;
        }
    }
    for(int i=1; i<=26; ++i) ans[i].id=i;
    sort(ans+1,ans+1+26);
    for(int i=1; i<=26; ++i) cout<<char(ans[i].id+‘a‘-1);
    return 0;
}
时间: 2024-10-08 02:50:24

Codeforces 510C的相关文章

(CodeForces 510C) Fox And Names 拓扑排序

题目链接:http://codeforces.com/problemset/problem/510/C Fox Ciel is going to publish a paper on FOCS (Foxes Operated Computer Systems, pronounce: "Fox"). She heard a rumor: the authors list on the paper is always sorted in the lexicographical order.

codeforces 510c (拓扑排序)

#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int N = 111111; int topo[205]; struct node { char a[105]; }e[105]; int n; int g[30][30]; int f[30]; int

codeforces 510C Fox And Names 拓扑排序

传送门:cf 510D 给定n个字符串,问能否存在这样的字母表,使得字符串的排序满足字典序.即依据新的字母表,排序满足字典序大小. 假设满足字典序,则我们可以依据已有的字符串得出各字母之间的大小关系,然后通过拓扑排序来判断是否存在可行解,输出任意解,因此只需要判断是否存在解即可. /****************************************************** * File Name: a.cpp * Author: kojimai * Create Time: 2

codeforces 510C Fox And Names 拓扑

题意:n个姓名,按照某种"字典序". 问如果存在这样的字典序,输出字典序'a'到'z'26个字母的顺序. 思路:拓扑排序.对于str[i]和str[i+1]如果在位置k出现不同,那么x=str[i][k]-'a'+1,y=str[i+1][k]-'a'+1,从x->y连一条边,y的入度in[y]++. 然后拓扑排序,如果形成环,就说明不行,不然依次输出对应字符.(ps:len1为str[i]的长度,len2为str[i+1]的长度,如果len1>len2且前len2个均相同

寒假集训日志(五)——期中测验

10道题目,A了4道,5道会做,5道不会,果然渣渣... 这次测验感觉无限段错误..一个是初始化的问题,还一个建树的过程出错,但还不知道错在哪里.先附上几道没A的题, 以后慢慢解决. B - 拓扑 Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 510C Description Fox Ciel is going to p

【codeforces 718E】E. Matvey&#39;s Birthday

题目大意&链接: http://codeforces.com/problemset/problem/718/E 给一个长为n(n<=100 000)的只包含‘a’~‘h’8个字符的字符串s.两个位置i,j(i!=j)存在一条边,当且仅当|i-j|==1或s[i]==s[j].求这个无向图的直径,以及直径数量. 题解:  命题1:任意位置之间距离不会大于15. 证明:对于任意两个位置i,j之间,其所经过每种字符不会超过2个(因为相同字符会连边),所以i,j经过节点至多为16,也就意味着边数至多

Codeforces 124A - The number of positions

题目链接:http://codeforces.com/problemset/problem/124/A Petr stands in line of n people, but he doesn't know exactly which position he occupies. He can say that there are no less than a people standing in front of him and no more than b people standing b

Codeforces 841D Leha and another game about graph - 差分

Leha plays a computer game, where is on each level is given a connected graph with n vertices and m edges. Graph can contain multiple edges, but can not contain self loops. Each vertex has an integer di, which can be equal to 0, 1 or  - 1. To pass th

Codeforces Round #286 (Div. 1) A. Mr. Kitayuta, the Treasure Hunter DP

链接: http://codeforces.com/problemset/problem/506/A 题意: 给出30000个岛,有n个宝石分布在上面,第一步到d位置,每次走的距离与上一步的差距不大于1,问走完一路最多捡到多少块宝石. 题解: 容易想到DP,dp[i][j]表示到达 i 处,现在步长为 j 时最多收集到的财富,转移也不难,cnt[i]表示 i 处的财富. dp[i+step-1] = max(dp[i+step-1],dp[i][j]+cnt[i+step+1]) dp[i+st