ZCMU - 2153: D.ly的排队问题

题目链接:点击打开链接

题目大意:略。

解题思路:Topo排序 + 优先队列。

AC 代码

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a)

using namespace std;

typedef long long ll;

const int MAXV=1010;
int vis[MAXV];
int mp[MAXV][MAXV]; // 邻接矩阵边连结
int in[MAXV]; // 入度
char rcd[MAXV]; // 最终记录
int n,len; // 顶点个数 最终记录长度

struct node
{
    int top;
    char ch;
};
node nds[MAXV];

struct pq_cmp
{
    bool operator()(node nd1,node nd2)
    {
        return nd1.ch>nd2.ch; // 字母字典序
    }
};

priority_queue<node,vector<node>,pq_cmp> pq;

void init()
{
    mem(vis,0);
    mem(mp,0);
    mem(in,0);
    mem(rcd,'\0');
    len=n=0;
    while(!pq.empty()) pq.pop();
}

int TopoSort()
{
//    int top=-1;
    node ndtop; // 临时变量,类似 top 变量
    ndtop.top=-1;
    for(int i=1;i<=n;i++)
    {
        if(in[i]==0)
        {
//            in[i]=top;
//            top=i;
            in[i]=ndtop.top;
            ndtop.top=i;
            nds[i].top=i;
            pq.push(nds[i]); // 数据加完后再在下面 if语句 取出,下面内层 for_k 当中也同理可得
        }
    }
    if(!pq.empty())
    {
        ndtop=pq.top();
        pq.pop(); // 注意每取一次,pop下
    }


    for(int i=1;i<=n;i++)
    {
        if(ndtop.top==-1)
        {
//            printf("No Answer!");
            return 0;
        }
        else
        {
            int j=ndtop.top;
            ndtop.top=in[j]; // 因为这里的 ndtop 上面保存在 j 里就没用了,所以这里可以替换新的数据
//            printf("%c",crr[j]);
            rcd[len++]=nds[j].ch;
            for(int k=1;k<=n;k++)
            {
                if(mp[j][k] && --in[k]==0)
                {
//                  in[k]=top;
//                  top=k;
                    in[k]=ndtop.top;
                    ndtop.top=k;
                    nds[k].top=k;
                    pq.push(nds[k]);
                }
            }
            if(!pq.empty())
            {
                ndtop=pq.top();
                pq.pop();
            }
        }
    }

    return 1;
}

int main()
{
    init();
    string s;
    while(cin>>s) // while(~scanf("%c>%c",&c1,&c2)) 多组数据时,没办法 Ctrl+Z
    {
        int from=s[0]-'A',to=s[2]-'A';

        if(vis[from]==0)
        {
            nds[++n].ch=s[0];
            vis[from]=n;
            from=n;
        }
        else
        {
            from=vis[from];
//            in[from]++; // 因为from指向to,所以并不是from的入度++
        }

        if(vis[to]==0)
        {
            nds[++n].ch=s[2];
            vis[to]=n;
            in[n]++;
            to=n;
        }
        else
        {
            to=vis[to];
            // 避免重复导致 in[to]++,一般情况topo题型很喜欢有重复数据
            if(mp[from][to]==1) continue;
            in[to]++;
        }

        mp[from][to]=1;
    }

    if(TopoSort())
    {
        for(int i=0;i<len;i++)
            printf("%c",rcd[i]);
    }
    else
        printf("No Answer!");
    puts("");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陆氪和他的那些代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值