题意是: 有重量从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;
}
}
}
}