大一第十四周训练G题 反向top排序

大一第十四周训练G题 反向top排序

题目:

Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that:

No two balls share the same label.
The labeling satisfies several constrains like “The ball labeled with a is lighter than the one labeled with b”.
Can you help windy to find a solution?
输入:
The first line of input is the number of test case. The first line of each test case contains two integers, N (1 ≤ N ≤ 200) and M (0 ≤ M ≤ 40,000). The next M line each contain two integers a and b indicating the ball labeled with a must be lighter than the one labeled with b. (1 ≤ a, b ≤ N) There is a blank line before each test case.
输出:
For each test case output on a single line the balls’ weights from label 1 to label N. If several solutions exist, you should output the one with the smallest weight for label 1, then with the smallest weight for label 2, then with the smallest weight for label 3 and so on… If no solution exists, output -1 instead.
样例:
输入:
5

4 0

4 1
1 1

4 2
1 2
2 1

4 1
2 1

4 1
3 2
输出:
1 2 3 4
-1
-1
2 1 3 4
1 3 2 4
——————————————————————————————————————
题意:
就是给你n个位置,让你放n个球,这n个球的重量从1到n,下面给你几组a和b,意思是a的重量小于b;
并且如果没有限制的话,前面的球的重量小于后面的球的重量。
思路:
刚开始看的时候直接就开始写top排序,上来就是一个答案错误;接下来想了想,就跟代码里面的注释一样。
——————————————————————————————————————
代码:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
/*
反向top排序:就是原本算的是入度,现在算出度;
因为本题是a的重量比b的轻,如果你找的是入度,就会
有多个入度为零的,这时候就成死棋了;并且本题是如
果没有限制条件的话就是前面的小于后面的,所以会想
到用优先队列先出来后面的,这时就会想到算出度的大小;
如果出度为零,就说明没有限制,全部入队,这时出来的
就是最大的那个放最重的,放完后把他身边的图清除,
如果有新的出度为零的点就入队,照着上面的继续循环就行了。
*/
int e[510][510];
int f[510];
int s[510];
int main()
{
    int t,i,j,n,m,a,b,k,flag,sum,tou;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(e,0,sizeof(e));
        //memset(book,0,sizeof(book));
        memset(f,0,sizeof(f));
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            if(e[a][b]==0)
            {
                e[a][b]=1;
                f[a]++;//记录出度的大小
            }
        }
        priority_queue<int> q;//利用优先队列
        k=n;
        for(i=1;i<=n;i++)
        {
            if(f[i]==0)
                q.push(i);
        }
        while(!q.empty())
        {
            tou=q.top();
            q.pop();
            s[tou]=k--;
            for(i=1;i<=n;i++)
            {
                if(e[i][tou])
                {
                    f[i]--;
                    if(f[i]==0)
                    {
                        q.push(i);
                    }
                }
            }
        }
        if(k)
            printf("-1\n");
        else
        {
            for(i=1;i<n;i++)
                printf("%d ",s[i]);
            printf("%d\n",s[i]);
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值