码迷,mamicode.com
首页 > 编程语言 > 详细

POJ 3687 Labeling Balls 逆向拓扑排序

时间:2015-01-22 13:28:22      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:c++

链接:

poj3687


题意:

有N个标号为1~N的小球,重量(不包括断言)依次增加 ,现给出M句断言 ,断言格式为a b

表示小球a轻于小球b     要求根据重量大小依次输出1~N号小球应在的的位置(重量递增)不满足断言则输出-1



题解:

因为重量是依次增加的  不能按常规的构造edge[a][b]=1生成拓扑排序

既然关系格式和一般拓扑排序是相反的  我们可以尝试着构造反向边edge[b][a]=1

indegree[a]++;   再根据小球标号从后往前进行拓扑排序,即可得到一幅完整的从大

到小的拓扑排序。

注意:

1.题目要求输出1~N号小球的位置,而不是完整的拓扑排序。

2.再构造边edge[b][a]=1的时候不能进行indegree[a]++;因为会有重边。






代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int map[505][505];
int indegree[505];
int ans[505];
int m;
int topsort()
{
    int i,j,loc,k=m;
    for(i=0; i<m; i++)
    {
        for(j=m; j>0; j--)         //从后往前
            if(!indegree[j])
            {
                loc=j;
                break;
            }
        if(j==0)
            return 0;
        ans[loc]=k--;             //ans[k--]=loc;
        indegree[loc]=-1;
        for(j=1; j<=m; j++)
            if(map[loc][j])
                indegree[j]--;
    }
    return 1;
}
int main()
{
    int i,j,t,a,b,n;
    scanf("%d",&t);
    while(t--)
    {
        memset(indegree,0,sizeof(indegree));
        memset(map,0,sizeof(map));
        scanf("%d%d",&m,&n);
        while(n--)
        {
            scanf("%d%d",&a,&b);
            map[b][a]=1;
        }
        for(i=1;i<=m;i++)
            for(j=1;j<=m;j++)
            if(map[i][j])
            indegree[j]++;
        if(topsort())
        {
            for(i=1; i<m; i++)
                cout<<ans[i]<<' ';
            cout<<ans[i]<<endl;
        }
        else
            cout<<-1<<endl;
    }
    return 0;
}







POJ 3687 Labeling Balls 逆向拓扑排序

标签:c++

原文地址:http://blog.csdn.net/axuan_k/article/details/43016345

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!