拓扑序列的最小字典序列

查错

考场上又写挂的一道签到题。。。

我们发现这题要求得到一个最小字典序列

显然找到所有序列然后排序是不可取的,

那么我们不能使用平常的拓扑排序方法,怎么搞使得在每次处理拓扑顺序的时候来维护呢?

用小根堆维护入度为0的点即可,输入的时候统计入度

{$inline on}
const maxn=100010;

type node=record
       pos,next:longint;
end;

var heap,getin,head,ans:array[0..maxn] of longint;
    edge:array[0..maxn*2] of node;
    n,m,cnt,top:longint;
    check:boolean;

procedure add(u,v:longint); inline;
begin
    inc(cnt);
    edge[cnt].pos:=v;
    edge[cnt].next:=head[u];
    head[u]:=cnt;
end;

procedure swap(var a,b:longint); inline;
begin
    a:=a xor b;
    b:=a xor b;
    a:=a xor b;
end;

procedure up(i:longint); inline;
var j:longint;
begin
    j:=i>>1;
    while j>0 do
    begin
        if heap[i]<heap[j] then
            begin
                swap(heap[i],heap[j]);
                i:=j;
                j:=j>>1;
            end
        else break;
    end;
end;

procedure down(i:longint); inline;
var j:longint;
begin
    j:=i<<1;
    while j<=top do
        begin
            if (j<top) and (heap[j]>heap[j+1]) then inc(j);
            if heap[i]>heap[j] then
                begin
                    swap(heap[i],heap[j]);
                    i:=j;
                    j:=j<<1;
                end
            else break;
        end;
end;

procedure init;
var i,x,y:longint;
begin
    read(n,m);
    for i:=1 to m do
        begin
            read(x,y);
            add(x,y);
            inc(getin[y]);
        end;
    for i:=1 to n do
        if getin[i]=0 then
            begin
                inc(top);
                heap[top]:=i;
            end;
    check:=true;
end;

procedure main;
var i,j,x,y:longint;
begin
    for j:=1 to n do
        begin
            if (top=0) then
                begin
                    check:=false;
                    break;
                end;
            x:=heap[1];
            ans[j]:=x;
            swap(heap[1],heap[top]);
            dec(top);
            down(1);
            i:=head[x];
            while i<>0 do
                begin
                    y:=edge[i].pos;
                    dec(getin[y]);
                    if getin[y]=0 then
                        begin
                            inc(top);
                            heap[top]:=y;
                            up(top);
                        end;
                    i:=edge[i].next;
                end;
        end;
end;

procedure print;
var i:longint;
begin
    if not check then writeln(‘OMG.‘)
    else
        begin
            for i:=1 to n-1 do
            write(ans[i],‘ ‘);
            writeln(ans[n]);
        end;
end;

begin
    init;
    main;
    print;
end.

时间: 2024-10-19 05:49:53

拓扑序列的最小字典序列的相关文章

python:将序列转成字典的用法

初学者学习笔记 如何将两个序列,变成字典? 这里的用法是通过并行迭代的[zip函数],zip函数是作用于任意多的序列,可以处理不等长度的序列,最短的序列"用完"的时候就停止了. 栗子: x = [1,2,3,4,5,6,7] y = ["one","two","three","four","five"] dic = dict(zip(x,y)) print(dic) {1: 'one',

Find Min In Rotated Sorted Array,寻找反转序列中最小的元素。

问题描述:寻找反转序列中最小的元素. 算法分析:和寻找某个数是一个道理,还是利用二分查找,总体上分两种情况.nums[left]<=nums[mid],else.但是,在截取子序列的时候,有可能得到一个顺序序列.如34512,截取后得到12,此时要对这种情况判断,因为是顺序的,所以,最左边的元素就是最小元素.这点区别于寻找target,因为寻找target是根据target和left,mid,right做比较判断的.所以就不用对这种顺序情况单独讨论了. 1 public int findMin(

括号序列的最小代价

题意 查看原题 这里有一个关于合法的括号序列的问题. 如果插入"+"和"1"到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的.例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(()))("是不合法的.我们这有一种仅由"(",")"

把一个序列转换成非严格递增序列的最小花费 POJ 3666

1 //把一个序列转换成非严格递增序列的最小花费 POJ 3666 2 //dp[i][j]:把第i个数转成第j小的数,最小花费 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <algorithm> 8 #include <vector> 9 #include <math.h> 10 // #include <memory.

把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend

1 //把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend 2 //dp[i][j]:把第i个数转成第j小的数,最小花费 3 //此题与poj 3666相似 a[i]转换成a[i]-i 4 5 #include <iostream> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <algorithm> 9 #include <

Old Sorting(转化成单调序列的最小次数,置换群思想)

Old Sorting Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1166 Description Given an array containing a permutation of 1 to n, you have to find the minimum number of swaps to sort the array i

传说中的华为Python笔试题——两等长整数序列互换元素,序列和的差值最小(修正)

有两个序列a,b,大小都为n,序列元素的值任意整形数,无序:要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小. 1. 将两序列合并为一个序列,并排序,得到sourceList2. 拿出最大元素Big,次大的元素Small3. 在余下的序列S[:-2]进行平分,得到序列max,min4. 将Small加到max序列,将Big加大min序列,重新计算新序列和,和大的为max,小的为min. 如下,提供递归版本和迭代版本的解体思路: #!/usr/bin/env py

51nod 1476 括号序列的最小代价 (括号题套路+反悔贪心)

题意:给一串只有'(' , ')' , '?' 的括号序列,每个?可以变成)或者(,代价分别为bi和ai,求变成合法序列的最小代价 思路:学习自最近的网络赛&&51nod贪心专题视频的思想,“反悔”,一般在获取收益有限制的情况下使用 先按某种“优”的策略贪心,如果不满足限制条件了,取一个修改后代价尽可能小的状态修改成满足条件的状态,得到新的满足限制下的最优解 这种贪心常常可以借助优先队列实现 然后是括号题的套路:把(当做1,把)当做-1,做前缀和 这题中,先当做所有的?都换成右括号,这是显

27.Next Permutation(下一个字典序列)

Level: ??Medium 题目描述: Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending