Codeforces 1213F Unstable String Sort

cf題面spa

中文題意

求一個由最多26個、最少k個小寫字母構成的,長度爲n的字符串,這個字符串要知足的要求是——當其中字母按照p和q兩個\(1\)~\(n\)的全排列從新排序時,新的字符串是按照升序排好序的(沒要求老字符串排好序)。.net

解題思路

虛擬賽時其實已經走到了想出正解的路上我在路上了。正解是這樣——對於排列p,將全部p[i]到p[i+1]連邊,對於q也將全部q[i]和q[i+1]連邊,那麼每條邊就表明前面位置的字母要小於等於後面位置的字母,那對於這個圖中的的全部強連通份量,上邊的字母應該都是相同的。因而縮點產生一個DAG,這個DAG前面的字母小於等於後面的字母,因而BFS一遍刪點,刪點的時候給該點賦一個字母,而後字母加一。最後輸出答案就好。code

虛擬賽時想到的是把p和q掃一遍,而後對於p和q中的一個位置上的不一樣數字,那麼這兩個數字表明的新位置之間的字母應該相同,可是這兩個位置之間的其餘數字也產生了其餘一對對位置,而後複雜度就上去了……亂七八糟的各類沒想清楚。排序

源代碼

#include<queue>
#include<cstdio>
#include<algorithm>
 
const int MAXN=2e5+5;
int n,k;
struct Edge{
    int nxt,to;
}e[MAXN<<2],e2[MAXN<<2];
int head[MAXN],cnt=1,head2[MAXN],cnt2=1;
inline void add(int u,int v)
{
    e[cnt]={head[u],v};
    head[u]=cnt++;
}
inline void add2(int u,int v)
{
    e2[cnt2]={head2[u],v};
    head2[u]=cnt2++;
}
int num=0,id[MAXN];//強連通份量數量
int ru[MAXN];//強連通份量的入度
int ind=1,dfn[MAXN],low[MAXN];
int stack[MAXN],top=0;
bool instack[MAXN];
void dfs(int u)
{
    dfn[u]=low[u]=ind++;
    stack[top++]=u;
    instack[u]=1;
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].to;
        if(!dfn[v])
        {
            dfs(v);
            low[u]=std::min(low[u],low[v]);
        }
        else if(instack[v]) low[u]=std::min(low[v],low[u]);
    }
    if(dfn[u]==low[u])
    {
        int v;
        num++;
        do{
            v=stack[--top];
            instack[v]=0;
            id[v]=num;
        }while(u!=v);
    }
}
char ans[MAXN];
void bfs()
{
    std::queue<int> q;
    for(int u=1;u<=num;u++) if(!ru[u]) q.push(u);
    char x='a';
    while(!q.empty())
    {
        int u=q.front();
        ans[u]=x;
        if(x!='z') x++;
        q.pop();
        for(int i=head2[u];i;i=e2[i].nxt)
        {
            int v=e2[i].to;
            ru[v]--;
            if(!ru[v]) q.push(v);
        }
    }
}
int main()
{
    // freopen("test.in","r",stdin);
    scanf("%d%d",&n,&k);
    for(int x=0;x<2;x++)
    {
        int temp;
        scanf("%d",&temp);
        for(int i=1,j;i<n;i++)
        {
            scanf("%d",&j);
            add(temp,j);
            temp=j;
        }
        scanf("%d",&temp);
        for(int i=1,j;i<n;i++)
        {
            scanf("%d",&j);
            add(temp,j);
            temp=j;
        }
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);//6>5>4>3>2>1
    if(num<k)
    {
        puts("NO");
        return 0;
    }
    for(int u=1;u<=n;u++)
    {
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(id[u]!=id[v]) add2(id[u],id[v]),ru[id[v]]++;
        }
    }
    puts("YES");
    bfs();
    for(int i=1;i<=n;i++)
    {
        putchar(ans[id[i]]);
    }
    return 0;
}
相關文章
相關標籤/搜索