BZOJ 4010 [HNOI2015]菜肴制作 拓扑排序

来源:互联网 发布:spss输入数据是问号 编辑:程序博客网 时间:2024/06/10 00:50

题意:给一个有向图,求一个拓扑序(可能没有),满足编号小的尽量靠前(优先1靠前再优先2靠前...)

Sol:

最近太颓废了,,,写点题压压惊

首先思考这样一种拓扑排序的方法:把普通BFS式拓扑排序的队列换成小顶堆,即优先放置编号小的点

这样并不能保证题目条件,比如

答案应该是3 1 2 而不是 2 3 1

我们发现这个方法实际是保证了字典序最小

再分析发现也保证了编号大的尽量靠后

于是我们把原图所有边反向,可以证明新图的每个拓扑序都与原图的一个拓扑序等价且一一对应

此时使用大根堆可保证编号小的尽量靠后,反过来就是题目的条件。

Code:

#include<bits/stdc++.h>#define cls(x) memset(x,0,sizeof x)using namespace std;const int maxn = 100009;int n,m,T;int first[maxn],du[maxn],a[maxn];struct edg{int next;int to;}e[maxn];int e_sum;priority_queue<int>heap;inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}inline void add_edg(int x,int y){e_sum++;du[y]++;e[e_sum].next=first[x];first[x]=e_sum;e[e_sum].to=y;}void ClearLove(){e_sum=0;cls(first);cls(du);while(!heap.empty()) heap.pop();}void Topsort(){int cnt=0;for(int i=1;i<=n;i++) if(!du[i]) heap.push(i);while(!heap.empty()){int x=heap.top();heap.pop();a[++cnt]=x;for(int i=first[x];i;i=e[i].next){int w=e[i].to;du[w]--;if(!du[w]) heap.push(w);}}if(cnt!=n) puts("Impossible!");else{for(int i=n;i>=1;i--) printf("%d ",a[i]);puts("");}}int main(){T=read();while(T--){ClearLove();n=read();m=read();for(int i=1;i<=m;i++){int x=read(),y=read();add_edg(y,x);}Topsort();}return 0;}



1 0
原创粉丝点击