BZOJ 4010 HNOI2015 菜肴制作 拓扑排序+堆

题目大意:给定一张无向图,求一个拓扑序,使:
1的位置最靠前
在保证上面的条件下使2的位置最靠前
在保证上面的条件下使3的位置最靠前
……
注意不是字典序最小!例如样例3

建立反图,对反图求字典序最大的拓扑序,然后反向输出即可。
我不知道为什么。真的不知道。
求个解答在线等。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
struct abcd{
    int to,next;
}table[M];
int head[M],tot;
int n,m;
int degree[M];
int stack[M],top;
void Add(int x,int y)
{
    table[++tot].to=y;
    table[tot].next=head[x];
    head[x]=tot;
}
void Initialize()
{
    memset(head,0,sizeof head);
    tot=1;
    memset(degree,0,sizeof degree);
}
namespace Priority_Queue{
    int heap[M],top;
    void Insert(int x)
    {
        heap[++top]=x;
        int t=top;
        while(t>1)
        {
            if(heap[t]>heap[t>>1])
                swap(heap[t],heap[t>>1]),t>>=1;
            else
                break;
        }
    }
    void Pop()
    {
        heap[1]=heap[top--];
        int t=2;
        while(t<=top)
        {
            if( t<top && heap[t+1]>heap[t] )
                ++t;
            if(heap[t]>heap[t>>1])
                swap(heap[t],heap[t>>1]),t<<=1;
            else
                break;
        }
    }
}
void Topology_Sort()
{
    using namespace Priority_Queue;
    int i;
    for(i=1;i<=n;i++)
        if(!degree[i])
            Insert(i);
    while(Priority_Queue::top)
    {
        int x=heap[1];Pop();
        stack[++::top]=x;
        for(i=head[x];i;i=table[i].next)
            if(!--degree[table[i].to])
                Insert(table[i].to);
    }
}
int main()
{
    int T,i,x,y;
    for(cin>>T;T;T--)
    {
        Initialize();
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            Add(y,x);
            degree[x]++;
        }
        top=0;
        Topology_Sort();
        if(top!=n)
            puts("Impossible!");
        else
        {
            for(i=n;i;i--)
                printf("%d ",stack[i],i==1?'\n':' ');
            puts("");
        }
    }
    return 0;
}

你可能感兴趣的:(堆,拓扑排序,bzoj,BZOJ4010)