Description
糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。
现在有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
注意此题不是保证字典序,而是要最小的尽量在前面。反向建图,将大的优先级放前面,然后逆序输出。
首先反向建图+逆序输出为一个答案。然后要保证最小的在最前面,因为是逆序输出,所以优先级要反过来
同时存在多个入度为0的点时,数字小的尽量靠前;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
#include<cstdio>
#include<stack>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int n,in[300010],head[300010],edgenum;
struct edge
{
int from,to,next;
}e[300010];
void add(int u,int v)//加边
{
int i;
for(i=head[u];i!=-1;i=e[i].next)//判断重边
{
if(e[i].to==v)
break;
}
if(i==-1)//不重边,记录入度
{
in[v]++;
edge E={u,v,head[u]};
e[edgenum]=E;
head[u]=edgenum++;
}
}
void solve()
{
priority_queue<int>q;//优先队列,大的优先
stack<int>s;
for(int i=1;i<=n;i++)
{
if(in[i]==0) q.push(i);//入度为0,存入队列
}
while(!q.empty())
{
int u=q.top();q.pop();
s.push(u);//入栈
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(--in[v]==0)//如果下一个点去除与上一个点的连接后入度为0;则存入队列
q.push(v);
}
}
while(s.size()>1)//逆序出栈
{
printf("%d ",s.top());
s.pop();
}
printf("%d\n",s.top());
s.pop();
}
int main()
{
int t,m,b,a;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
edgenum=0;
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
add(b,a);
}
solve();
}
return 0;
}
队列存储:
#include <cstdio>
#include <cstring>
#include <queue>
#define maxn 100002
using namespace std;
int head[maxn], indegree[maxn], ans[maxn];
struct Node{
int to, next;
} map[maxn];
void topoSort(int n)
{
priority_queue<int> Q;//优先队列
int i, u, id = 1;
for(i = 1; i <= n; ++i)
if(!indegree[i]) Q.push(i);
while(!Q.empty()){//大的先弹出
ans[id++] = u = Q.top();
Q.pop();
for(i = head[u]; i != -1; i = map[i].next)
if(--indegree[map[i].to]==0) Q.push(map[i].to);
}
for(i = n; i >= 1; --i)//逆向输出 ,小的尽量排在前面
if(i != 1) printf("%d ", ans[i]);
else printf("%d\n", ans[i]);
}
int main()
{
int t, n, m, a, b, i;
scanf("%d", &t);
while(t--){
memset(indegree, 0, sizeof(indegree));
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
for(i = 0; i < m; ++i){
scanf("%d%d", &a, &b);
map[i].to = a;
map[i].next = head[b];
head[b] = i;
++indegree[a];
}
topoSort(n);
}
return 0;
}