题意:有编号 1~n 的球,每个球的质量不同,质量从 1 到 n 不等,给出一系列比较,分别是两个编号的球的大小关系,求一个序列满足上述关系,并且从编号 1 开始依次选择可选的最小质量,输出每个球的质量。
一开始以为就是排好拓扑序之后输出就行了,但这样是按质量从小到大输出的,事实上要输出编号从小到大的球的质量,因此其实是要输出每个球在序列中的位置。改了之后用优先队列从小到大直接做还是 WA 的,之后发现因为前面的优先放置哪个会影响后面小编号的位置,比如 3号<1号 ,2号无比较关系,就会使优先队列先出 2号,再出 3号,最后出 1号,那么 1号的质量就变成最大的了,但事实上,可以 3号最小,1号其次,2号最大,这样 1号的质量就比之前的序列小了,所以我们需要按 1号>3号来建边,然后优先队列先出编号大的,这样就能使编号小的在这一层里最晚出,也就是最轻。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h>
2 #include<string.h>
3 #include<queue>
4 #include<vector>
5 using namespace std;
6
7 int id[205],ma[205][205],n,ans[205],ans1[205];
8
9 bool topo(){
10 priority_queue<int>q;
11 for(int i=1;i<=n;++i)if(!id[i])q.push(i);
12 int cnt=0;
13 while(!q.empty()){
14 int u=q.top();
15 q.pop();
16 ans[++cnt]=u;
17 for(int i=1;i<=n;++i){
18 if(i!=u&&ma[u][i]){
19 id[i]--;
20 if(!id[i])q.push(i);
21 }
22 }
23 }
24 if(cnt==n)return 1;
25 return 0;
26 }
27
28 int main(){
29 int T;
30 scanf("%d",&T);
31 while(T--){
32 int m;
33 scanf("%d%d",&n,&m);
34 memset(ma,0,sizeof(ma));
35 memset(id,0,sizeof(id));
36 bool f=1;
37 while(m--){
38 int a,b;
39 scanf("%d%d",&a,&b);
40 if(a==b)f=0;
41 else if(!ma[b][a]){
42 ma[b][a]=1;
43 id[a]++;
44 }
45 }
46 if(!f)printf("-1\n");
47 else{
48 if(!topo())printf("-1\n");
49 else{
50 for(int i=1;i<=n;++i){
51 ans1[ans[i]]=n-i+1;
52 }
53 for(int i=1;i<=n;++i){
54 printf("%d",ans1[i]);
55 if(i==n)printf("\n");
56 else printf(" ");
57 }
58 }
59 }
60 }
61 return 0;
62 }