codeforce E - Minimal Labels+hdu 4857

两个题目的意思差不多 都是希望得出的拓扑序如果有多种 要求输出字典序小的情况

这里引用一个大佬的博客 关于为什么不能直接建图然后用小根堆解决这个问题(http://blog.csdn.net/rgnoH/article/details/75253355 : 出处)

再解答一个小问题:

主要是在和六号@Mogician_Evian 交流之后想到的:这道题可以用小根堆做吗?

看起来可以!

可能的操作是:

1.题目中说什么,就怎么连边,并记录入度。 
2.执行Topsort标准操作,压入小根堆中。 此时从1到N,依次给取出的堆顶元素进行编号。

可能的分析方法和上面的是类似的。

然而并不能!

为什么?看看这一组数据:

3 1 
3 1

正解应该是

2 3 1

然而小根堆会输出

3 1 2

为什么?

我们要的并不是让新编号小的数尽量靠前,而是让答案数组靠前的数尽量小! 
小根堆讨论就只是让新编号小的数尽量靠前了。

豁然开朗!

hdu 4857 ac代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
int in[200001];
int mark[200001];
vector<int > edge[200001];
int n,m;
/*
struct node
{
    int x;
    int point;
    bool operator <(node a,node b)
    {
        return a.point > b.point;
    }
};
*/
void init()
{
    for(int i=0; i<=n; i++)
    {
        in[i]=0;
        edge[i].clear();
    }
}
void topo()
{
    priority_queue<int,vector<int>,less<int> >q; //大根堆
    for(int i=1; i<=n; i++)
    {
        if(in[i]==0) q.push(i);
    }
    int ret=n;
    while(!q.empty())
    {
        int now=q.top();
        q.pop();
        mark[ret--]=now;
        for(int i=0; i<edge[now].size(); i++)
        {
            int temp=edge[now][i];
            in[temp]--;
            if(in[temp]==0) q.push(temp);
        }
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        init();
        for(int i=1; i<=m; i++)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            edge[b].push_back(a);
            in[a]++;
        }
        topo();
        cout<<mark[1];
        for(int i=2; i<=n; i++) cout<<' '<<mark[i];
        cout<<endl;
    }

    return 0;
}

 

posted @ 2017-07-19 20:20  猪突猛进!!!  阅读(125)  评论(0编辑  收藏  举报