2021牛客多校10 F Train Wreck(搜索,优先队列)

https://ac.nowcoder.com/acm/contest/11261/F
在这里插入图片描述
题意:给一组入栈出栈操作,给出入栈出栈操作元素(可重复),求入栈序列,使得栈内任意时刻状态都不相同。
思路:入栈和出栈等价于树的先根遍历,则题转化为求一颗任意从根出发的树枝都不相同的树。
可以先先根遍历,深搜建树,然后广搜填充元素,元素从多往少填才能保证树枝尽可能不相同。最后按照建树顺序输出元素即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
string parentheses;//括号序列
int partp=0;//遍历到括号序列的位置
int book[maxn+10];//记录颜色数量
struct colorNode{
    int type;
    int num;
};//颜色结点,包括种类和数量
bool operator<(const colorNode x,const colorNode y){//优先队列重载小于号
    return x.num<y.num;
}
priority_queue<colorNode>colorque;
struct treeNode{
    vector<int>son;
    int color;
}tree[maxn+10];//树结点,包括儿子和颜色
int nowid=0;//当前遍历到的树结点
void dfs(int father){//子树根节点
    while(parentheses[partp]=='('){//如果是左括号,说明要继续往下搜索,进入子树
        partp++;
        nowid++;//结点顺次编号
        tree[father].son.push_back(nowid);
        dfs(nowid);
    }
    partp++;//右括号说明要返回上一层
    return;
}
bool bfs(){
    queue<int>que;
    que.push(0);
    while(!que.empty()){
        for(int i=0;i<que.size();i++){
            int now=que.front();
            que.pop();
            vector<colorNode>coltemp;
            for(int j=0;j<tree[now].son.size();j++){
                int Son=tree[now].son[j];
                que.push(Son);
                if(colorque.empty())return 0;
                colorNode col=colorque.top();
                colorque.pop();
                tree[Son].color=col.type;
                col.num--;
                if(col.num!=0){
                    coltemp.push_back(col);
                }
            }
            for(int j=0;j<coltemp.size();j++){
                colorque.push(coltemp[j]);
            }
        }
    }
    return 1;
}
int main(){
    int N;
    cin>>N;
    parentheses+='(';
    cin>>parentheses;
    parentheses+=')';//补全树根
    for(int i=0;i<N;i++){
        int x;
        scanf("%d",&x);
        book[x]++;
    }
    for(int Type=0;Type<=maxn;Type++){
        if(book[Type]!=0)colorque.push({Type,book[Type]});
    }
    dfs(0);
    if(bfs()==0){
        printf("NO\n");
        return 0;
    }
    else{
        printf("YES\n");
    }
    for(int i=1;i<=nowid;i++){
        if(i!=1)printf(" ");
        printf("%d",tree[i].color);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值