• codeforces1213F tarjan缩点+拓扑排序


    题意

    给定两个长度为n的排列p和q,构造一个字符串s满足(s[p_i]<=s[p_{i+1}])(s[q_i]<=s[q_{i+1}]),且满足字符串中不同字符的个数不少于k。

    分析

    建一个有向图,(p_i)(p_{i+1})连一条有向边,(q_i)(q_{i+1})连一条有向边。

    一条链上的点我们可以贪心的让每个点的字符递增,递增到'z'后,让其余字符全部等于'z',而在同一个环中的所有点的字符一定是相同的,可以把所有环都缩成一个点,那么这张图就变成了有向无环图,可以直接拓扑排序做了。

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define pb push_back
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=2e5+10;
    int n,k;
    int low[maxn],dfn[maxn],st[maxn],inst[maxn],top=-1,cnt,scnt,sc[maxn];
    vector<int>g[maxn];
    set<int>f[maxn];
    int d[maxn],rk[maxn];
    int res=-1;
    void dfs(int u){
    	dfn[u]=low[u]=++cnt;
    	st[++top]=u;
    	inst[u]=1;
    	for(int x:g[u]){
    		if(!dfn[x]){
    			dfs(x);
    			low[u]=min(low[u],low[x]);
    		}else if(inst[x]){
    			low[u]=min(low[u],dfn[x]);
    		}
    	}
    	if(low[u]==dfn[u]){
    		scnt++;
    		while(true){
    			int x=st[top--];
    			sc[x]=scnt;
    			inst[x]=0;
    			if(x==u) break;
    		}
    	}
    }
    int main(){
    	ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	cin>>n>>k;
    	int x,y;
    	cin>>x;
    	int rt=x;
    	for(int i=1;i<n;i++){
    		cin>>y;
    		g[x].pb(y);
    		x=y;
    	}
    	cin>>x;
    	for(int i=1;i<n;i++){
    		cin>>y;
    		g[x].pb(y);
    		x=y;
    	}
    	for(int i=1;i<=n;i++){
    		if(!dfn[i]) dfs(i);
    	}
    	for(int i=1;i<=n;i++){
    		for(int x:g[i]){
    			if(sc[i]!=sc[x]) f[sc[i]].insert(sc[x]);
    		}
    	}
    	for(int i=1;i<=n;i++)
            for(int x:f[i])
                d[x]++;
    	queue<int>q;
    	int mx=-1;
    	for(int i=1;i<=scnt;i++) rk[i]=-1;
    	for(int i=1;i<=scnt;i++){
    		if(d[i]==0) q.push(i),rk[i]=mx=0;
    	}
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int x:f[u]){
    			rk[x]=max(rk[u]+1,rk[x]);
    			rk[x]=min(25,rk[x]);
    			mx=max(mx,rk[x]);
    			if(--d[x]==0) q.push(x);
    		}
    	}
    	if(mx+1<k) cout<<"NO
    ";
    	else{
    		cout<<"YES
    ";
    		for(int i=1;i<=n;i++){
    			cout<<(char)(rk[sc[i]]+'a');
    		}cout<<'
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    BZOJ1307: 玩具 单调队列
    BZOJ4415: [Shoi2013]发牌 树状数组+二分
    BZOJ2456: mode
    BZOJ2982: combination Lucas
    BZOJ4195: [Noi2015]程序自动分析 并查集
    BZOJ2563: 阿狸和桃子的游戏 贪心
    BZOJ5281: [Usaco2018 Open]Talent Show 01分数规划+01背包
    一种斐波那契博弈(Fibonacci Nim)
    网易云深度剖析Kubernetes优化与实践
    360°透视:云原生架构演进
  • 原文地址:https://www.cnblogs.com/xyq0220/p/11729187.html
Copyright © 2020-2023  润新知