正题
题目链接:https://www.luogu.com.cn/problem/P3243
题目大意
nnn个数,有mmm个要求形如xxx在yyy的前面,现在要求在i−1i-1i−1尽量靠前的情况下iii尽量靠前(i>1)(i>1)(i>1)
求这个序列
解题思路
这个很显然要求是张有向图无环图,然后若第iii个数排在第xxx位,那么pi=xp_i=xpi=x,那么就是要求ppp的字典序最小。但是发现如果直接拓扑排序+优先队列就会导致拓扑序的字典序最小,不符合题意,但是如果我们将拓扑图反过来跑就是正确答案了。
这样子跑是保证了反过来的字典序最大,那么小的一定在后面也就是保证了反过来后pip_ipi小的一定在前面。
时间复杂度O(n)O(n)O(n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+10;
struct node{int to,next;
}a[N];
int T,n,m,tot,cnt,in[N],ls[N],top[N];
priority_queue<int> q;
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;in[y]++;return;
}
void topsort(){for(int i=1;i<=n;i++)if(!in[i])q.push(i);while(!q.empty()){int x=q.top();top[++cnt]=x;q.pop();for(int i=ls[x];i;i=a[i].next){int y=a[i].to;in[y]--;if(!in[y])q.push(y);}}return;
}
int main()
{scanf("%d",&T);while(T--){tot=cnt=0;memset(ls,0,sizeof(ls));memset(in,0,sizeof(in));scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addl(y,x);}topsort();if(cnt!=n)printf("Impossible!");else{for(int i=n;i>=1;i--)printf("%d ",top[i]);}putchar('\n');}return 0;
}