查错 (拓扑排序+堆维护)

来源:互联网 发布:python 库安装过程 编辑:程序博客网 时间:2024/06/05 08:41

查错
[Description]
一天,考试题神坑了。不过,我们的Mosaic还是成功的写出了程序,当然,结果比较赞:“TBMW*TBMW*”,结果被痛骂了一顿。经过漫长的检查,Mosaic发现他的程序有M处错误,现在要做的就是修改程序了。但是他发现,这M处错误存在复杂的联系,有的错误必须在其他错误之前改正,否则事情会变得很麻烦,因此,他开始写另一个程序来解决这个问题……

[Input]
第一行两个整数:M,N。N表示程序之间的依赖关系数量
以下N行每行两个整数a,b。表示第a处错误必须在第b处错误之前改正。

[Output]
一行,按改正顺序输出错误编号。若有多解,请输出字典序小的解(即尽量使编号小的错误先被改正)。如果无解,输出“OMG.”(不含引号)。

[Sample]
Sample Input
5 5
1 2
2 3
1 3
1 4
4 5
Sample Output
1 2 3 4 5

[Hint]
对于100%的数据,有0 < M,N ≤ 100000
保证没有重边。

感谢姜大神的标程让我学会了拓扑排序(以前对于topsort一窍不通),而且这道题的数据比较大,需要堆维护,很经典。 我们首先建边,记录每个点的入度,把每一个入度为零的点(其实就是目前可以做的任务)放进堆里进行维护。然后每一次都弹出堆里面的第一个元素,当这个元素出堆之后,所有必须在他之后的任务的入度都要减一,如果有些任务的入度减到0了,那么将这个任务入堆。反复的弹出第一个任务并且记录弹出元素的数量,然后删边,维护堆,直到堆里不再有元素。如果弹出的元素数量小于点数,那就说明有些任务不能完成,输出OMG,否则按顺序输出弹出的元素即可。

program mys;type ab=^node;node=recordends:longint;next:ab;end;var i,j,k,m,n,chu,t,x,y:longint;p:array[0..200000]of ab;f,a,d:array[0..200000]of longint;procedure com(x,y:longint);var i:ab;begin i:=p[x];new(p[x]);p[x]^.ends:=y;p[x]^.next:=i;end;procedure put(x:longint);var i,j,k,g,h:longint;begininc(t);f[t]:=x;j:=t;i:=j div 2;while (f[i]>f[j]) and (j>1) dobegink:=f[j]; f[j]:=f[i]; f[i]:=k;j:=i;i:=j div 2;end;end;function get:longint;var ff,son,p:longint;begin get:=f[1];f[1]:=f[t];dec(t);ff:=1;while ff*2<=t do begin if (ff*2+1>t)or(f[ff*2]<f[ff*2+1]) then son:=ff*2else son:=ff*2+1;if f[ff]>f[son] thenbeginp:=f[ff]; f[ff]:=f[son]; f[son]:=p;end;ff:=son;end;end;procedure fa;var i:ab;y,x:longint;begin if t>0 then repeatx:=get;inc(chu);a[chu]:=x;i:=p[x];while i<>nil do begin y:=i^.ends;dec(d[y]);if d[y]=0 then put(y);i:=i^.next;end;p[x]:=nil;until t<=0;end;begin assign(input,'correct.in'); reset(input);assign(output,'correct.out'); rewrite(output);readln(n,m);for i:=1 to m do begin readln(x,y);com(x,y);inc(d[y]);end;for i:=1 to n do if d[i]=0 then put(i);chu:=0;fa;if chu<n then begin writeln('OMG.'); close(input); close(output);end;for i:=1 to chu-1 do write(a[i],' ');write(a[chu]);close(input);close(output);end.
0 0