CF1213F Unstable String Sort

题目传送门

思路

我们可以根据 \(p_i\)\(q_i\) 建有向边,边 \(u,v\) 表示 \(u\) 需要小于等于 \(v\)

然后跑一遍缩点。

不难发现在一个强连通分量里的点必须要相等,于是最多的不同字母个数即为 \(\min(26,tot)\),其中 \(tot\) 表示强连通分量的个数。

接下来我们已经把图缩成了一个 DAG,于是直接跑拓扑排序即可。

代码

#include<bits/stdc++.h>
using namespace std;
int const N=2e5+10;
char color[N];int rd[N],n,k,p[N],q[N];
vector<int>a[N],b[N];
int dfn[N],co[N],low[N],s[N],ind[N],top,cnt,tot;
inline void tarjan(int x){
    dfn[x]=low[x]=++cnt;s[++top]=x;ind[x]=1;
    for (auto v:a[x])
        if (!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]);
        else if (ind[v]) low[x]=min(low[x],low[v]);
    if (low[x]==dfn[x]){
        ++tot;
        while (1){
            int X=s[top--];
            co[X]=tot;ind[X]=0;
            if (!(x^X)) break;
        }
    }
}
inline void topo_sort(){
    queue<int>q;
    for (int i=1;i<=n;++i) if (!rd[i]) q.push(i),color[i]='a';
    while (!q.empty()){
        int x=q.front();q.pop();
        for (auto v:b[x]){--rd[v];color[v]=max(color[v],min('z',char(color[x]+1)));if (!rd[v]) q.push(v);}
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>k;
    for (int i=1;i<=n;++i) cin>>p[i];
    for (int i=2;i<=n;++i) a[p[i-1]].push_back(p[i]);
    for (int i=1;i<=n;++i) cin>>q[i];
    for (int i=2;i<=n;++i) a[q[i-1]].push_back(q[i]);
    for (int i=1;i<=n;++i) if (!dfn[i]) tarjan(i);
    if (tot<k) return cout<<"NO\n",0;
    for (int i=1;i<=n;++i)
        for (auto v:a[i])
            if (co[i]^co[v]) b[co[i]].push_back(co[v]),++rd[co[v]];
    topo_sort();
    cout<<"YES\n";
    for (int i=1;i<=n;++i) cout<<color[co[i]];cout<<'\n';
    return 0;
}
posted @ 2022-11-09 10:07  Tx_Lcy  阅读(49)  评论(1)    收藏  举报