poj3687 拓扑序

题意:有编号 1~n 的球,每个球的质量不同,质量从 1 到 n 不等,给出一系列比较,分别是两个编号的球的大小关系,求一个序列满足上述关系,并且从编号 1 开始依次选择可选的最小质量,输出每个球的质量。

一开始以为就是排好拓扑序之后输出就行了,但这样是按质量从小到大输出的,事实上要输出编号从小到大的球的质量,因此其实是要输出每个球在序列中的位置。改了之后用优先队列从小到大直接做还是 WA 的,之后发现因为前面的优先放置哪个会影响后面小编号的位置,比如 3号<1号 ,2号无比较关系,就会使优先队列先出 2号,再出 3号,最后出 1号,那么 1号的质量就变成最大的了,但事实上,可以 3号最小,1号其次,2号最大,这样 1号的质量就比之前的序列小了,所以我们需要按 1号>3号来建边,然后优先队列先出编号大的,这样就能使编号小的在这一层里最晚出,也就是最轻。

 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
");
47         else{
48             if(!topo())printf("-1
");
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("
");
56                     else printf(" ");
57                 }
58             }
59         }
60     }
61     return 0;
62 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/4797631.html