题意:有n个球,他的重量从1到n个重量单位,每一个球都有自己的重量单位,并不会重复,现在给你一些顺序a b,表示a的重量比b小,让你按字典序最小找出符合所有条件的序列每一个元素表示i-th个球在序列中的位置。
想法:开始以为直接正向建边然后,top_sort从小到大找,然后输出就好了。但是这样是不对的,因为我们可以知道,如果用这种方法,得到的是球的编号的字典序输出。
5 4
5 1
4 2
1 3
2 3
就是这组数据,给你的编号是no.1<no.5,no.4<no.2......这样得到的答案是:4,2,5,1,3。这里的数字标识的还是编号no.x,而正确结果是2,4,5,3,1。
如果用贪心的思想:我们知道了位置上的数字的大小关系,那么我们找到最大的一个数,把它赋值n,在通过它找到比他小但是除它以外最大的所有的数,然后把他们中编号最大的找出,赋值n-1..........,用贪心很难找到他的确切的起点,所以倒着来。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
int n,m;
int map[200+5][200+5];
int ind[200+5];
int id[200+5];
int ans[200+5];
struct node
{int x;friend bool operator < (node a,node b){return a.x<b.x;}
}e;
void Input()
{scanf("%d %d",&n,&m);memset(map,0,sizeof(map));memset(ind,0,sizeof(ind));for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);if(map[b][a]) continue;map[b][a]=1;ind[a]++;}
}
int top_sort()
{int top=n;priority_queue<node>q;while(!q.empty()) q.pop();for(int i=1;i<=n;i++){if(!ind[i]){e.x=i;q.push(e);}} while(!q.empty()){e=q.top();q.pop();ans[e.x]=top--;for(int i=1;i<=n;i++){if(map[e.x][i]){if(--ind[i]==0){node k;k.x=i;q.push(k);}}}}return top==0;
}
void treatment()
{if(!top_sort()){printf("-1\n");return;}for(int i=1;i<=n;i++){printf("%d%c",ans[i],i==n?'\n':' ');}
}
int main()
{int t;scanf("%d",&t);while(t--){Input();treatment();}return 0;
}