[逆向拓扑排序]POJ3687 Labeling Balls

看了几页书上的网络流感觉不想看了,找了前面几章的题目打算水一水练手,结果碰上这个题也是很囧。

一开始做是正向,从轻到重建边,记录入度,搞优先队列让小序号的先出队,同时搞一个普通队列把每次选的入度为0的点记录下来,结果一发WA。

后来仔细看了看题目,结果要输出的是结点的标号。

比如最开始第一个选的入度为0的点是5,那么我的第一个答案就是5了,其实题目不是这个意思,第一个答案应该是1第几个被选出队,2第几个被选出队。

然而。。我竟然把样例过了。。

好吧。把记录答案的普通队列改成了数组,记录结点第几个出队。

结果又是一发WA。

想水题不认真就是这个下场。

其实这题应该反向建边,然后逆序拓扑,给序号大的标上大标号,因为正向搞其实是在做序号的贪心,我觉得也是可以的,但是思维和代码都比逆向难。

具体见代码和注释。

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int map[205][205];
int in[205];
int ans[205];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        memset(in,0,sizeof(in));
        memset(map,0,sizeof(map));
        memset(ans,0,sizeof(ans));

        int n, m, a, b;
        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; ++i)
        {
            scanf("%d%d", &a, &b);
            if( !map[b][a])
            {
                map[b][a] = 1; //重到轻建边
                in[a] += 1;
            }
        }

        priority_queue<int>q; //默认是优先把序号大的出列 因为是逆向建图 需要给序号的标上大的标号
        int num = n, cnt = num;
        for(int i = n; i>=1; --i) if( !in[i]) q.push( i);
        while( !q.empty())
        {
            int u=q.top(); q.pop(); num-=1;
            for(int i = 1;i <= n; ++i)
            {
                if(map[u][i] && ( (--in[i]) == 0)) q.push( i);
            }
            ans[u] = cnt-- ; //给序号大的附上大标号
        }
        if(num != 0) { puts("-1"); }
        else {
            for(int i = 1; i <= n; ++i) printf("%d ", ans[i]);
            puts("");
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值