[題解]拓撲排序(優先隊列/字典序最小)

 考试抄书(日常)


P2038 -- 小叶子的故事之写代码 

时间限制:1000MS      内存限制:131072KB 

题目描述(correct.cpp)

小叶子要写一道砍手题,要写N个函数。小叶子作为一名强迫症患者,喜欢按从上到下的顺序写函数,他会在写代码之前给要写的函数排个顺序依次完成。现在小叶子给你M个关系如(x,y),表示函数y要调用函数x(即函数x要写在函数y之前)。假设小叶子不会使用函数声明,请你设计一个字典序最小的序列。如果没法得到这样一个序列,则输出“OMG.”(没有引号)

输入格式(correct.in)

第一行有两个整数N,M。

接下来M行每行两个数x、y,表示x要写在y前面

输出格式(correct.out)

一行N个数,表示字典序最小的序列

样例输入

5 5

1 2

2 3

1 3

1 4

4 5

样例输出

1 2 3 4 5

数据规模与约定

对于 40% 的数据,N,M <= 5,000。

对于 100% 的数据,N,M <= 100,000。


 

裸的拓撲排序,字典序最小<=>把隊列換成優先隊列

#include
#include
#include
#include
using namespace std;
const int maxn=100010;
int n,m;
struct node{
    int v,nxt;
}e[maxn*2];
int head[maxn],cnt,tot;
int in[maxn],a[maxn];
void add(int u,int v){e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt;}
void topo(){
    priority_queue<int,vector<int>,greater<int> >q;
    for(int i=1;i<=n;i++)
    if(in[i]==0)q.push(i);
    while(!q.empty()){
        int x=q.top();q.pop();
        a[++tot]=x;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].v;
            if(--in[y]==0)q.push(y);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,x,y;i<=m;i++){
        scanf("%d%d",&x,&y);
        add(x,y);in[y]++;
    }
    topo();
    if(tot==n)
    for(int i=1;i<=tot;i++)
    printf("%d ",a[i]);
    else printf("OMG.");
}

 

转载于:https://www.cnblogs.com/superminivan/p/10703079.html

你可能感兴趣的:([題解]拓撲排序(優先隊列/字典序最小))