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("");
}

猜你喜欢

转载自blog.csdn.net/dream_weave/article/details/80700754