题意:有编号 1~n 的球,每个球的质量不同,质量从 1 到 n 不等,给出一系列比较,分别是两个编号的球的大小关系,求一个序列满足上述关系,并且从编号 1 开始依次选择可选的最小质量,输出每个球的质量。
一开始以为就是排好拓扑序之后输出就行了,但这样是按质量从小到大输出的,事实上要输出编号从小到大的球的质量,因此其实是要输出每个球在序列中的位置。改了之后用优先队列从小到大直接做还是 WA 的,之后发现因为前面的优先放置哪个会影响后面小编号的位置,比如 3号<1号 ,2号无比较关系,就会使优先队列先出 2号,再出 3号,最后出 1号,那么 1号的质量就变成最大的了,但事实上,可以 3号最小,1号其次,2号最大,这样 1号的质量就比之前的序列小了,所以我们需要按 1号>3号来建边,然后优先队列先出编号大的,这样就能使编号小的在这一层里最晚出,也就是最轻。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
using namespace std; int id[],ma[][],n,ans[],ans1[]; bool topo(){
priority_queue<int>q;
for(int i=;i<=n;++i)if(!id[i])q.push(i);
int cnt=;
while(!q.empty()){
int u=q.top();
q.pop();
ans[++cnt]=u;
for(int i=;i<=n;++i){
if(i!=u&&ma[u][i]){
id[i]--;
if(!id[i])q.push(i);
}
}
}
if(cnt==n)return ;
return ;
} int main(){
int T;
scanf("%d",&T);
while(T--){
int m;
scanf("%d%d",&n,&m);
memset(ma,,sizeof(ma));
memset(id,,sizeof(id));
bool f=;
while(m--){
int a,b;
scanf("%d%d",&a,&b);
if(a==b)f=;
else if(!ma[b][a]){
ma[b][a]=;
id[a]++;
}
}
if(!f)printf("-1\n");
else{
if(!topo())printf("-1\n");
else{
for(int i=;i<=n;++i){
ans1[ans[i]]=n-i+;
}
for(int i=;i<=n;++i){
printf("%d",ans1[i]);
if(i==n)printf("\n");
else printf(" ");
}
}
}
}
return ;
}