vijos P1790拓扑编号
来源:互联网 发布:淘宝原创男装店铺 编辑:程序博客网 时间:2024/04/29 07:42
描述
H国有n个城市,城市与城市之间有m条单向道路,满足任何城市不能通过某条路径回到自己。现在国王想给城市重新编号,令第i个城市的新的编号为a[i],满足所有城市的新的编号都互不相同,并且编号为[1,n]之间的整数。国王认为一个编号方案是优美的当且仅当对于任意的两个城市i,j,如果i能够到达j,那么a[i]应当<a[j]。
优美的编号方案有很多种,国王希望使1号城市的编号尽可能小,在此前提下,使得2号城市的编号尽可能小...依此类推。
格式
输入格式
第一行读入n,m,表示n个城市,m条有向路径。
接下来读入m行,每行两个整数:x,y
表示第x个城市到第y个城市有一条有向路径。
输出格式
输出一行:n个整数
第i个整数表示第i个城市的新编号a[i],输出应保证是一个关于1到n的排列。
样例1
样例输入1[复制]
5 44 11 35 32 5
样例输出1[复制]
2 3 5 1 4
限制
每个测试点1s
提示
30%的测试点满足:n <= 10, m <= 10
70%的测试点满足:n <= 1000, m <= 10000
100%的测试点满足:n <= 100000, m <= 200000
输入数据可能有重边,可能不连通,但保证是有向无环图。
来源
Topcode
分析:拓扑排序+堆优化
从前向后找每次找到序号最小的入度为0的点?样例就不对。(脑补一下为什么。。。)
从后向前反向贪心?可行。每次找出度为0的编号最大的点,删反向边,减出度,并令这个点的编号当前最大。
一个有向无环图中出度为0的点一定在最后,那么根据序号大小从大到小编号,保证小编号一定留给序号小的且尽量靠前的点。
Code:
program t;var n,m,i,x,y,l,j,p:longint; head,c,ans:array[1..100000]of longint; edge:array[1..200000,1..2]of longint;begin read(n,m); for i:=1 to n do head[i]:=-1; for i:=1 to m do begin read(x,y); l:=l+1; edge[l,1]:=x; edge[l,2]:=head[y]; head[y]:=l; c[x]:=c[x]+1; end; for i:=n downto 1 do begin j:=n; while (j>0)and(c[j]<>0) do j:=j-1; ans[j]:=i; c[j]:=n+1; p:=head[j]; while p<>-1 do begin c[edge[p,1]]:=c[edge[p,1]]-1; p:=edge[p,2]; end; end; for i:=1 to n do write(ans[i],' ');end.
但这题的数据范围是100000拓扑排序复杂度O(n^2)
在每次找出度为0的点时用堆优化,复杂度O(nlogn)
Code:
program tt;var n,m,i,x,y,l,j,p:longint; head,c,ans,heap:array[1..100000]of longint; edge:array[1..200000,1..2]of longint;procedure add(x:longint);var i,j,t:longint;begin heap[l]:=x; i:=l; while i>1 do begin j:=i shr 1; if heap[j]<heap[i] then begin t:=heap[j];heap[j]:=heap[i];heap[i]:=t; i:=j;end else break; end;end;procedure updata;var i,j,t:longint;begin i:=1; while i shl 1<=l do begin j:=i shl 1; if (j<l)and(heap[j]<heap[j+1]) then j:=j+1; if heap[i]<heap[j] then begin t:=heap[i];heap[i]:=heap[j];heap[j]:=t; i:=j;end else break; end;end;begin read(n,m); for i:=1 to n do head[i]:=-1; for i:=1 to m do begin read(x,y); l:=l+1; edge[l,1]:=x; edge[l,2]:=head[y]; head[y]:=l; c[x]:=c[x]+1; end; for i:=1 to n do if c[i]=0 then begin l:=l+1;add(i); end; for i:=n downto 1 do begin j:=heap[1];//每次加入度为0的点,用大根堆维护编号 ans[j]:=i; c[j]:=n+1; heap[1]:=heap[l];l:=l-1;updata; p:=head[j]; while p<>-1 do begin c[edge[p,1]]:=c[edge[p,1]]-1; if c[edge[p,1]]=0 then begin l:=l+1;add(edge[p,1]);end; p:=edge[p,2]; end; end; for i:=1 to n do write(ans[i],' ');end.
0 0
- vijos P1790拓扑编号
- 【vijos】【拓扑排序】拓扑编号
- Vijos 1790 拓扑编号(拓扑排序+堆优化)
- 拓扑编号
- Vijos1790 拓扑编号 拓扑排序
- 【Vijos1790】拓扑编号
- Vijos[1028]魔族密码 Trie树+拓扑排序
- 产生冠军 拓扑定理(如何对字符串进行编号)
- 拓扑
- 拓扑
- 拓扑
- 拓扑
- vijos 1070
- vijos 1020
- VIJOS 1180
- VIJOS-P1130
- vijos-1788
- vijos-1385
- git学习(4)---工作流
- Windows多线程基础(6):线程间通信1(互锁函数、CriticalSection)
- JQuery 实现锚点链接之间的平滑滚动
- 黑客入门需要了解的8个简洁方便的安全工具
- 树莓派学习笔记(5):成功实现NAS家庭服务器(流媒体播放、文件共享及下载机)
- vijos P1790拓扑编号
- 浏览器新实用功能开发研究:单页富客户端应用的会话/视图状态复制及远程同步功能
- Andriod分辨率适配 Android UI 设计
- 各种排序算法的分析及java实现
- AngularJs--XHRs & Dependency Injection
- Linux TC(Traffic Control)框架原理解析
- Win7中的页目录
- Android 图表生成开源之AChartEngine(整理)
- Thread 学习 -同步问题1