题意:有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;
}