题意是: 有重量从1到N 的 球,和1- N的标签,对球进行标记。
给出M个关系A B 表示 标签A的球的重量< 标签B球 的重量。
要求对其排序 ,重量从小到大, 同时使标签1 尽可能的 排在前边,满足标签1的球之后,在使得标有标签二的球尽可能的靠前,依次排序。。。 如果有这样的结果输出结果如果没有输出-1;
这个题目很诡异。。。。 不仔细读题的话,很可能出错,
For each test case output on a single line the balls' weights from label 1 to labelN.
这句话是说要输出球的重量,而不是标签。。。。排完序后的顺序是标签的顺序,其下表是重量。。。
这个题目要求标签一尽可能的
通过数据来分析这个题目:
有关系
5 6
6 1
4 7
4 2
2 7
9 8
构成图就是
5-->1 -->6
4-->2-->7
9-->8
3
假如出现这种情况,我们要使得1尽可能排在前边
那么 就应该是先确定 顺序是
5 1
再使得 2 尽可能的排在前边
5 1 4 2
依次确定 5 1 4 2 3 6 7 9 8
想想这样取有什么性质??
我们应该先取 排在 1 前边的标签 和 1 也就是这里的 5 1 ,排在一后边不能添加,因为我们要使得2 尽可能排在前边
在取 排在 2 前边的标签 5 1 4 2 。在取3 ,
再取 4 前边的 发现4 已经取出了 就不加操作 ,继续向后找。。。。
这样的贪心取标签的过程,就是最终标签的顺序。。。。。
觉着最有可能的拓扑排序 无法完成。。。。
刚才给出的值是链状的结果 ,。。。
如过形成了图。。。
例如 :
5-->2-->1
4-->3-->1
这样的情况 我们先取出 1 前 也就是 (4 3 5 2 ),但是这不是最优解。。。 最优解应该是(5 2 4 3),要使得 2 尽可能排在前边。。。。。 在图这样情况, 我们取出1 后在对 1 前边的出现的数排序即可 然后将 1 前边的 排好序后放在1 之前
这样拓扑排序也很难实现。。。。
既然先处理a,再处理a之前的出现的数。。既然每次取最小值 ,不能实现, 那每次取出最大值,剩余的就是最小值。。
这样我们先取出 1 在取出3 ,
结果就变成了
5-->2
4
这时再去 4 ,在取 2 ,在去5 。。。。
反向拓扑排序,每次取出最大值。。。用到优先队列。。
反向拓扑排序,就应该反向构图,来拓扑排序。。
拓扑排序用上优先对列 ,能够实现每次取出最大最小值的功能,可以使拓扑排序时,队列中这些入度为0 的点,按一定的顺序遍历。
附上代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; int t; int n,m; int adj[220][220]; int in_deg[220]; int answer[220]; void init(){ // 初始化邻接矩阵 和 入度、。。。。 for(int i=0;i<=n;i++){ for(int j=0;j<=n;j++){ adj[i][j]=0; } in_deg[i]=0; } } bool bfs (){ int outsum = 0;// 判断是否有环 。。 如果出队操作的个数 等于N 的话就没环,小于N 就有环。。。。 priority_queue<int>proq; for(int i=1;i<=n;i++){ if(in_deg[i]==0){ proq.push(i); } } int an_idx =n; while(!proq.empty()){ int top = proq.top(); outsum++; proq.pop(); answer[top]=an_idx; // 要求的是 标签对应最小重量。 拓扑序下标就是重量。。 an_idx--; for(int i=1;i<=n;i++){ if(adj[top][i]){ in_deg[i]--; if(!in_deg[i]){ proq.push(i); } } } } if(outsum==n) return true; return false; } int main(){ scanf("%d",&t); for(int i=1;i<=t;i++){ scanf("%d%d",&n,&m); init(); bool again=false; // 判重 。。。没判重 会wa 的很惨 for(int j=1;j<=m;j++){ int a,b; scanf("%d%d",&b,&a);//反向构图。。 if(a!=b){ if(!adj[a][b]){ adj[a][b]=1; in_deg[b]++; } }else{ again =true; } } if(again){ cout << -1<<endl; } else{ bool bo = bfs(); if(bo){ for(int i=1;i<n;i++){ printf("%d ",answer[i]); } printf("%d\n",answer[n]); }else{ cout <<-1<<endl; } } } }