题目大意:
糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。
现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。
负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。
那么你就要安排大家的顺序。我们保证一定有解。
基本思路:
就是拓扑排序的基础上加上了限定序号大小,反向存边,优先队列存,反向输出;
这样一开始找找到的就是独立的点或者最后一个点,然后开始进入循环,优先队列默认出最大,那么先出来的就是符合条件的最大的,然后找到和此点有边的点,很显然,每次都是讲满足条件的最大的id存下,最后倒序输出就好了
代码如下:
#include<iostream> #include<string> #include<vector> #include<queue> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 50000+10; int ind[maxn],tp[maxn]; vector<int>gra[maxn]; int main(){ int cas; scanf("%d",&cas); while(cas--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ gra[i].clear(); ind[maxn]=0; } int u,v; while(m--){ scanf("%d%d",&u,&v); ind[u]++; gra[v].push_back(u); } priority_queue<int>pq; for(int i=1;i<=n;i++){ if(!ind[i]){ pq.push(i); } } int cnt=0; while(!pq.empty()){ int u=pq.top(); pq.pop(); tp[cnt++]=u; int sz=gra[u].size(); for(int i=0;i<sz;i++){ int v=gra[u][i]; ind[v]--; if(!ind[v]){ pq.push(v); } } } for(int i=cnt-1;i>=0;i--){ if(i==cnt-1){ printf("%d",tp[i]); }else{ printf(" %d",tp[i]); } } printf(" "); } return 0; }