Train Wreck

题目链接:https://ac.nowcoder.com/acm/contest/108199/F

题意:

给定一个括号栈序列,以及一些颜料,要求每次入栈后,栈中的颜料序列不能重复出现

输出符合条件的颜料序列。

思路:

可以将括号栈操作看作建树过程

初始树的根节点为0

1.入栈操作

在当前节点下延申出一个子节点,并将子节点设置为当前节点

2.出栈操作

将当前节点回溯至其父节点上

那么约束条件即为:树上任意一个非叶子节点的直接儿子节点都两两不同

那么对于一个节点,对其直接儿子节点的染色过程就有说法了

由于颜料个数有限,为了尽量使直接儿子节点们两两不同,我们需要先取出颜料个数最多的那些颜料进行染色

因为如果颜料个数少的颜料染色,到后面颜料的选择就会变少,使约束条件不成立(即到达某个直接儿子节点时没有可供选择的颜料了)的概率增加

为了维护颜料个数多的颜料,需要使用优先队列。

void dfs(int u){
    if(!f)return;
    
    vector<pii>p;
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==fa[u])continue;
        if(q.size()){
            pii color=q.top();
            q.pop();
            ans[v]=color.se;
            if(color.fi>1){
                p.pb((pii){color.fi-1,color.se});
            }
        }else{
            f=0;return;
        }
    }

    for(int i=0;i<p.size();i++){
        q.push(p[i]);
    }

    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==fa[u])continue;
        dfs(v);
        if(!f)return;
    }
}
void solve(){
    int n;cin>>n;
    int now=0;
    int cnt=1;
    rep(i,1,2*n){
        char ch;cin>>ch;
        if(ch=='('){
            int temp=now;
            now=cnt++;
            fa[now]=temp;
            e[now].pb(fa[now]);
            e[fa[now]].pb(now);
        }else{
            now=fa[now];
        }
    }
    map<int,int>mp;
    rep(i,1,n){
        int x;cin>>x;mp[x]++;
    }
    for(auto[x,y]:mp){
        q.push({y,x});
    }
    dfs(0);
    if(!f){
        cout<<"NO"<<endl;
        return;
    }
    cout<<"YES"<<endl;
    rep(i,1,n){
        cout<<ans[i]<<' ';
    }
}
posted @ 2025-05-08 20:06  Marinaco  阅读(11)  评论(0)    收藏  举报
//雪花飘落效果