1 / 14

《 食物链 》 解题报告

《 食物链 》 解题报告. 00130004 杭杰. 问题描述. 三类动物 A 、 B 、 C , A 吃 B , B 吃 C , C 吃 A 。 给出 K 句话来描述 N 个动物(各属于 A 、 B 、 C 三类之一)之间的关系,格式及意义如下: 1 X Y :表示 X 与 Y 是同类; 2 X Y :表示 X 吃 Y 。 K 句话中有真话有假话,当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 1 ) 当前的话与前面的某些真的话冲突,就是假话; 2 ) 当前的话中 X 或 Y 比 N 大,就是假话; 3 ) 当前的话表示 X 吃 X ,就是假话。

Télécharger la présentation

《 食物链 》 解题报告

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 《食物链》解题报告 00130004 杭杰

  2. 问题描述 • 三类动物A、B、C,A吃B,B吃C,C吃A。 • 给出K句话来描述N个动物(各属于A、B、C三类之一)之间的关系,格式及意义如下: • 1 X Y:表示X与Y是同类; • 2 X Y:表示X吃Y。 • K句话中有真话有假话,当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 1) 当前的话与前面的某些真的话冲突,就是假话; 2) 当前的话中X或Y比N大,就是假话; 3) 当前的话表示X吃X,就是假话。 • 求假话的总数。

  3. 问题描述(2) • 输入: • 第一行是两个整数N和K,以一个空格分隔。 以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 若D=1,则表示X和Y是同类。 若D=2,则表示X吃Y。 • 输出: • 只有一个整数,表示假话的数目。 • 约束条件: • 1 <= N <= 50000,0 <= K <= 100000。

  4. 结果计数器加一 将当前输入加入已知关系集 进行简单判定 进行逻辑判定 初步分析 • 这一题的基本思路是对每句话判断真假,进行统计,最后输出统计结果。 • 根据假话的条件2和条件3,我们可以判定一些假话(简单判定),其他的需要根据这句话与前面的话的关系来判定(逻辑判定)。 • 对一句话的判定流程如下:

  5. 算法一 • 此题的算法设计重点在于 逻辑判定和关系添加部分。 • 一个容易想到的思路: • 用二维数组s存放已知关系: • S[X][Y] = -1:表示X与Y关系未知; • S[X][Y] = 0:表示X与Y是同类; • S[X][Y] = 1:表示X吃Y; • S[X][Y] = 2:表示Y吃X。 • 对每个读入的关系s(x,y),检查S[x][y]: • 若S[x][y]=s,则继续处理下一条; • 若S[x][y] = -1,则令S[x][y]=s,并更新S[x][i]、S[i][x]、S[y][i]和S[i][y] (0<=i<=n)。 • 若S[x][y] != s且S[x][y] != -1,计数器加1。

  6. 算法一(2) • 复杂度: • 以上算法需要存储一个N×N的数组,空间复杂度为O(N2)。 • 对每一条语句 • 进行关系判定时间为O(1) • 加入关系时间为O(N) • 总的时间复杂度为O(N*K) • 0<=N<=50000,0<=K<=100000,复杂度太高。

  7. 进一步分析 • 对于任意a≠b,a、b属于题中N个动物的集合S,当且仅当S中存在一个有限序列(P1, P2, …, Pm)(m≥0)使得aP1、P1P2、…、Pm-1Pm、Pmb(或m=0时的ab)之间的相对关系均已确定时,b对a的相对关系才可以确定。 • 由上面可知,我们不需要保留每对个体之间的关系,只需要为每对已知关系的个体保留一条路径aP1P2…Pmb(m≥0)其中aP1、P1P2、…、 Pm-1Pm、Pmb之间的关系均为已知。

  8. 解决方案 • 使用树结构!!!

  9. 算法二 • 用结点表示每个动物,边表示动物之间的关系。采用父结点表示法,在每个结点中存储该结点与父结点之间的关系。 • 结点的数据结构: Struct node { int relation; struct node *parent; };

  10. 算法二(2) • 初始状态下,每个结点单独构成一棵树。 • 逻辑判断: • 分别找到两个结点a、b所在树的根结点ra、rb,并在此过程中计算a与ra、b与rb之间的相对关系。 • 若ra!=rb,此句为真话,将a、b之间的关系加入; • 若ra=rb,则可计算出r(a,b)=f( r(a,ra) , r(b,rb) ) • 若读入的关系与r(a,b)矛盾,则此句为假话,计数器加1; • 若读入的关系与r(a,b)一致,则此句为真话。

  11. 算法二(3) • 加入关系: • 只需要加入不在同一棵树上的两个结点之间的关系。 • 加入关系的过程就是将两棵树合并,使一棵树成为另一棵树的子树。 • 为了减小树的深度,将深度较小的一棵树的父指针指向另一棵树的根结点。

  12. 复杂度 • 逻辑判定的时间取决于树的深度,树的平均深度为O(Log(N))。 • 在逻辑判定时得到两棵树的根,并分别算出两个结点与其根结点之间的关系的基础上,添加关系只需要算出两棵树的根结点之间的关系,并修改其中一个根结点的relation域和父指针,时间复杂度为O(1)。 • 总的时间复杂度为K*Log(N)。 • 只需要为每个结点保存一个结构体,空间复杂度为O(N)。

  13. 算法优化 • 在逻辑判定过程中,我们需要遍历两个结点到根结点之间的路径,如果把被访问的结点记录下来,将它的父指针指向根结点,同时更新它与父结点的关系,则可以减少下次对这条路径上的结点及其子结点的访问时间。 • 实现:用一个指针数组按序存放该路径上的所有结点的地址,在找到根结点后,再将这些点的父指针指向根结点,并根据相邻结点与根结点的关系更新该结点与根结点之间的关系。

  14. 总结 • 根据题目的特点和复杂度要求,选择适当的数据结构,特别注意树结构的应用。 • 在树结构的应用中注意路径压缩,以减小深度,避免退化成线性结构。

More Related