【Vijos1790】拓扑编号
来源:互联网 发布:java超市管理系统 编辑:程序博客网 时间:2024/04/30 23:04
H国有n个城市,城市与城市之间有m条单向道路,满足任何城市不能通过某条路径回到自己。
现在国王想给城市重新编号,令第i个城市的新的编号为a[i],满足所有城市的新的编号都互不相同,并且编号为[1,n]之间的整数。国王认为一个编号方案是优美的当且仅当对于任意的两个城市i,j,如果i能够到达j,那么a[i]应当<a[j]。
优美的编号方案有很多种,国王希望使1号城市的编号尽可能小,在此前提下,使得2号城市的编号尽可能小...依此类推。
【题解】
反向建图,拓扑排序时每次选取入度为0的编号最大的节点,最后反向输出,注意题目所求的不是1-n编号对应的城市而是1-n城市对应的编号,编号最大节点使用优先队列维护。
【代码】
program escape;var t, o: longint; a: array[-1..200001, 1..2] of longint; b: array[-1..300000] of longint; i, j, k, n, m: longint; c: array[0..300000] of longint; cd: array[-1..300000] of longint; d: array[-1..300000] of longint; e: array[-1..300000] of longint; procedure qsort(x, y: longint); var i, j, m1, m2, t: longint; begin i := x; j := y; m1 := a[(i + j) div 2, 2]; m2 := a[(i + j) div 2, 1]; repeat while (a[i, 2] < m1) or ((a[i, 2] = m1) and (a[i, 1] < m2)) do Inc(i); while (a[j, 2] > m1) or ((a[j, 2] = m1) and (a[j, 1] > m2)) do Dec(j); if i <= j then begin t := a[i, 1]; a[i, 1] := a[j, 1]; a[j, 1] := t; t := a[i, 2]; a[i, 2] := a[j, 2]; a[j, 2] := t; Inc(i); Dec(j); end; until i > j; if i < y then qsort(i, y); if j > x then qsort(x, j); end; procedure hup(m: longint); var i: longint; t: longint; begin i := m div 2; while i <> 0 do begin if c[m] < c[i] then break else begin t:=c[m];c[m]:=c[i];c[i]:=t;m := i; i := m div 2; end; end; end; procedure hdown(i: longint); var j: longint; t: longint; begin if c[i * 2] < c[i * 2 + 1] then j := i * 2 + 1 else j := i * 2; if (i * 2 + 1 > c[0]) and (j = i*2+1) then Dec(j); while (c[i] < c[j]) and (j <= c[0]) do begint:=c[i];c[i]:=c[j];c[j]:=t; i := j; if c[i * 2] < c[i * 2 + 1] then j := i * 2 + 1 else j := i * 2; if (i * 2 + 1 > c[0]) and (j = i*2+1) then Dec(j); //堆操作不能忘了这句话- - end; end; procedure insert(x: longint); begin Inc(c[0]); c[c[0]] := x; hup(c[0]); end; function top: longint; var t: longint; begin top := c[1]; t := c[1]; c[1] := c[c[0]]; c[c[0]] := t; Dec(c[0]); hdown(1); end;begin readln(n, m); for i := 1 to m do readln(a[i, 1], a[i, 2]); a[m + 1, 2] := 0; c[0] := 0; qsort(1, m); for i := 1 to n do b[i] := 0; for i := 1 to n do cd[i] := 0; for i := 1 to m do if b[a[i, 2]] = 0 then b[a[i, 2]] := i; for i := 1 to m do Inc(cd[a[i, 1]]); for i := 1 to n do if cd[i] = 0 then insert(i); if (c[0] = 0) then writeln(-1) else for i := 1 to n do begin k := top; d[n - i + 1] := k; e[d[n - i + 1]] := n - i + 1; j := b[k]; while a[j, 2] = k do begin Dec(cd[a[j, 1]]); if cd[a[j, 1]] = 0 then insert(a[j, 1]); Inc(j); end; if (i <> n) and (c[0] = 0) then begin writeln(-1); break; end; if i = n then begin for j := 1 to n - 1 do Write(e[j], ' '); writeln(e[n]); end; end;end.
0 0
- 【Vijos1790】拓扑编号
- Vijos1790 拓扑编号 拓扑排序
- 拓扑编号
- 【vijos】【拓扑排序】拓扑编号
- vijos P1790拓扑编号
- Vijos 1790 拓扑编号(拓扑排序+堆优化)
- 产生冠军 拓扑定理(如何对字符串进行编号)
- 拓扑
- 拓扑
- 拓扑
- 拓扑
- 编号89757 编号89757 编号89757 编号89757 编号89757
- LANA编号
- 编号管理
- 混淆编号
- 自动编号
- 身份证编号
- 自动编号
- 端口被占用的处理方法
- hibernate与Mysql-Dialect问题
- 实现Collection和Map接口的常用类的几种循环方法
- Android touch事件处理流程
- C++ 单例模式的实现
- 【Vijos1790】拓扑编号
- Android TextPaint 写文字 水平、垂直居中
- 2014/11/6
- 第三章总结
- 黑马程序员——面向对象<二> 笔记第四篇
- atitit。gui 界面皮肤以及换肤总结 java .net c++
- Unity3D学习之第三日(前面学习的总结,做了一个小项目)
- 程序员是否优秀的重要因素之一
- 三角形