糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。
现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。
负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。
那么你就要安排大家的顺序。我们保证一定有解。
现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。
负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。
那么你就要安排大家的顺序。我们保证一定有解。
Input
第一行一个整数T(1 <= T <= 5),表示测试数据的个数。
然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。
然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。
然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。
然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。
Output
对每个测试数据,输出一行排队的顺序,用空格隔开。
Sample Input
1 5 10 3 5 1 4 2 5 1 2 3 4 1 4 2 3 1 5 3 5 1 2
Sample Output
1 2 3 4 5
傻傻的我以为可以直接从小到大输出,直接就wa,后来才知道要反相建图,列入1->4->5,6->2,要是按正常的拓扑排序,1-4-5-6-2,可是题意是小的尽量放在前面,即1-6-2-4-5,所以我们可以反相建图,把两者调换一下位置,估计你们看到这还是不明白,我到现在也很糊涂,不过你仔细看看代码,应该可以看懂。
#include<cstdio> #include<cstring> #include<queue> #include<iostream> using namespace std; const int g=310000; struct Edge{ int from,to,next; }edge[g]; int head[g],in[g]; int dis[g],m,n,num; void init() { memset(head,-1,sizeof(head)); memset(in,0,sizeof(in)); num=0; } void add(int u,int v) { edge[num].from =u; edge[num].to =v; edge[num].next =head[u]; head[u]=num++; } void topo() { int i,j,k=0; priority_queue<int> q; while(!q.empty() ) q.pop() ; for(i=1;i<=n;i++) { if(in[i]==0) q.push(i); } while(!q.empty() ) { int now=q.top() ; q.pop() ; dis[k++]=now; in[now]=-1; for(i=head[now];i!=-1;i=edge[i].next ) { int h=edge[i].to ; in[h]--; if(in[h]==0) { q.push((h)); } } } for(i=k-1;i>0;i--) printf("%d ",dis[i]); printf("%d\n",dis[0]); } int main() { int i,j,a,b,t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); for(i=0;i<m;i++) { scanf("%d%d",&a,&b); add(b,a); in[a]++; } topo(); } return 0; }