【日常学习】【拓扑排序】家谱树&FZU1483 Sicily1424 奖金 题解

拓扑排序的定义 简单来说就是给你一个图写出一个序列 图中如果a通向b 那么序列中A必须排在B前面

拓扑排序可能有很多结果 必须是有向无环图 可以利用拓扑排序来判定环的存在 当然也可以用神奇的SPFA 但是拓扑排序时间复杂度很低 只有O(V+E)

基本实现思路是 每次取出入度为0的点 然后删除与它相连的边 直到没有边  如果还有边但是找不到入度为0的点 说明有环

学习这个算法联系了两道题目 很经典很单纯 但是一般没有OJ有评测 奖金这道题目在福州大学OJ和中山大学萌萌哒Sicily上找到了评测(为什么要叫西西里呢?)

先放题目:

家谱树

【题目描述】

有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。

给出每个人的孩子的信息。

输入一个序列,使得每个人的后辈都比那个人后列出。

【输入】

第一行一个整数(1<=N<=100),表示家族的人数。

接下来N行,第I行表示第I个人的儿子。

每行最后是0表示描述完毕。

【输出】

输出一个序列,使得每个人的后辈都比那个人后列出。

如果有多解输出任意一解。

【输入样例】

5

0

4 5 1 0

1 0

5 3

0

3 0

【输出样例】

2 4 5 3 1

这道题目显然只需要一次拓扑排序 输出任意一个序列就可以了 不要求输出结果而是序列 因此要在过程中数组保存出队的元素 另外这道题目没有环

放代码:

普通循环的代码

用了STL队列的代码 更加方便易懂

奖金

【题目描述】

由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。

于是Mr.Z下令召开m方会谈。每位参加会谈的代表提出了自己的意见:“我认为员工a的奖金应该比b高!”Mr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元。

【输入】

第一行两个整数n,m,表示员工总数和代表数;

以下m行,每行2个整数a,b,表示某个代表认为第a号员工奖金应该比第b号员工高。

【输出】

若无法找到合法方案,则输出“-1”;否则输出一个数表示最少总奖金。

输入输出样例

reward.in

2 1

1 2

reward.out

201

【数据范围】

80%的数据满足n<=1000,m<=2000;

100%的数据满足n<=10000,m<=20000。

这道题目有环,要求输出结果而不是过程,因此解唯一。采用分层处理的办法,对于每一个奖金级别集中计算。代码注释说的很清楚,此处不再赘述。

这个思路参考了黄学长的代码,但是他的代码是错误的,我已经在他的博客中指正了。

但是仍有一个疑问,本代码在Sicily测得AC,福州大学WA了 所以本代码可能也有一定问题

尝试写了STL队列版 但是时间关系没有写完 而且本题queue实现有些困难 如果成功了之后补上

上代码

最后补充一下 几个很好的将拓扑排序的文章:

http://blog.csdn.net/dm_vincent/article/details/7714519  这个讲的有点高深,有兴趣的可以看一下

http://blog.csdn.net/liwen_7/article/details/7298736 浅显地介绍了原理

http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/topological_sort.asp 太原理工的精品课演示 有助于理解

其实所有博客都不如自己理解了最好···

努力努力向Tarjan进发!!!

——烟敛寒林簇,画屏展;天际遥山小,黛眉浅。

时间: 2024-10-17 17:07:00

【日常学习】【拓扑排序】家谱树&FZU1483 Sicily1424 奖金 题解的相关文章

hdu3342(Legal or Not)----- 学习拓扑排序的好例题

经典拓扑排序 点击打开链接 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is so harmonious that just like a big family. Every day,many "holy cows" like HH, hh, AC, ZT, lcc, BF, Qinz and so on chat on-line to exch

拓扑排序,树的直径模板(CF14D 枚举删边)

HDU4607 树的直径 #include <stdio.h> #include <string.h> #include <iostream> #include <queue> #include <vector> using namespace std; #define N 100005 #define INF 1<<30 int n,dis[N],E; bool vis[N]; vector<int>G[N]; //注意

HDU 5195 DZY Loves Topological Sorting (拓扑排序+线段树)

题目地址:HDU 5195 简直受不了了..BC第二题都开始线段树+拓扑排序了... 这题很容易想到拓扑排序过程中贪心,但是贪心容易TLE,所以需要用数据结构去维护,我用的是线段树维护.每次找入度小于等于k的编号最大的点,这样就可以保证字典序一定是最大的. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorith

P3588 [POI2015]PUS(拓扑排序+线段树)

P3588 [POI2015]PUS 对于每个$(l,r,k)$,将$k$个位置向剩下$r-l-k+1$个位置连边,边权为$1$,这样就保证$k$个位置比剩下的大 先给所有位置填$1e9$保证最优 然后拓扑排序填数 填的数不在$[1,1e9]$内或者出现环,即为不合法 但是这样边数过多会超时 于是考虑线段树优化建图 把$n$个点建成线段树,每个节点向左右儿子连边,边权为0. 这样每次连一个区间$[l,r]$就只需要$log(r-l+1)$次 注意不合法情况要枚举完整 #include<iostr

【日常学习】【IDA*】codevs2449 骑士精神题解

题目描述 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务. 输入描述 Input Description 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,

【日常学习】【背包DP】codevs1014 装箱问题题解

转载请注明出处 来自CSDN用户ametake 题目来自NOIP2011PJ4 上题目 题目描述 Description 有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数). 要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小. 输入描述 Input Description 一个整数v,表示箱子容量 一个整数n,表示有n个物品 接下来n个整数,分别表示这n 个物品的各自体积 输出描述 Output Descr

【日常学习】【二分查找】cidevs3297 木材加工题解

开始调教codeblocks 小翅膀还真是难调啊╮(╯▽╰)╭ 去年提高一最后一天也是讲的二分 今年卢大爷还是讲的二分 不过加了一点倍增LCA和Hash(虽然最后并没有时间讲Hash╮(╯▽╰)╭) 今天下午的效率很高,尤其是结交认识了省实验的老乡靳老师JLF神犇 还有广饶一中的项老师XZC神犇= =顺带还有众省实验广饶大牛讨论的不亦乐乎 相比上午一直在推命苦的家族遗传病患者实在是好多了= = 这道题本身不难= =然而···先上题目吧 题目描述 Description 木材厂有一些原木,现在想把

【日常学习】【深搜】codevs2452 扫雷题解

题目来源:05年四川省选 转载请注明出处 [ametake版权所有]http://blog.csdn.net/ametake欢迎来看 题目描述 Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,"余"人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字表示和它8连通的格子里面雷的数目.现在棋盘是n×2的,第一列里面某些格子是雷,而第二列没有雷, 由于第一列的雷可能有多种方案

HDU 2094 拓扑排序

产生冠军 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 12031    Accepted Submission(s): 5583 Problem Description 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛. 球赛的规则如下: 如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能