最近在看数据结构中的图,总感觉没有学好,这次想再花些时间搞懂弄熟,期间有几个经典的例子,分享出来:
1.文字游戏问题:
【问题描述】一些暗门中隐含着很多有趣的文字游戏,一些考古学家要试着破解这些谜题以便将门打开,因为除此之外别无选择,所以解开这些谜题对于我们而言是很重要的。
这里每扇门上都有一些具有磁性的盘子,每个盘子上均有一些字母。这些盘子必须按照这样的顺序排列:前一个盘子上单词的最后一个字母是后一个盘子上的单词的第一个首字母,例如,单词acm的下一个单词是motorola。编写一个程序去读这些盘子上的文字并判断这些单词是否都能按照以上的规则排列,以便把门打开
【输入】该问题的输入由T个例子组成。输入文件第一行给出T。每个测试例子的第一行是一个整数N,表示盘子的个数(1~10 000)。接下来输入N行数据,每行包含一个单词,每个单词最少由2个,最多由1 000个小写字母组成,同一个单词可重复出现。
示例:
3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok
【输出】程序应能检测出盘子是否可以按照上述规则的顺序摆放,每扇门的盘子都要用上,并只用一次。如果某单词出现n次,那么该单词需要被使用n次。如果存在这样的序列,输出“Ordering is possible。”;否则,输出“The door cannot be opened”。
【分析】可以看出,该问题可以抽象成在途中找一条欧拉回路的问题,利用深度优先遍历对构建的图进行深度遍历,并判断是否存在欧拉回路即可。
2. 道路修建问题
【问题描述】现有N个村子,这些村子的编号为1~N要修建一条路,这些路应把这些村子两两连接起来。如果A村与B村相连,那么要么村A与村B之间有条路,要么A村与B村之间有条路,并且B村与C村之间也有条路。我们已知村子与村子之间已经修建了一些路,这里的任务是修建剩下的路以使所以的村子都连上,并使路的总长度最小(来源:PKU Monthly,kicc)
【输入】第1行包含一个整数N(3~100),N是村子的数量,接下来有N行,这N行中的第i行包含N个整数,这N个整数中的第j个代表村与村之间的距离,这个距离应该在[1,1 000]内,即村i与村j之间的距离。接下来的是一个整数Q(0 ~ N*(N+1)/2),然后是Q行数据,每一行包含两个整数a与b,(a<b,[1~N]),意味着村a村b之间的之间的路已修建。
示例:
3
0 990 693
990 0 179
693 179 0
1
1 2
【输出】程序应在一行中输出一个整数,这个数代表了要把这些村子连接起来所需的最短的总路程。例如若是按照上述给出的示例进行输入,将得到输出179
【分析与解答】这是一个在图中求最小生成树的问题,按照克鲁斯卡尔算法在图中求解最小生成树即可成功解决了该问题。
3. 回家路线问题
【问题描述】贝茜在外面的田里,她现在想回到谷仓,因为明早约翰会叫醒她并要她去挤牛奶,所以她希望在那之前能睡得越长时间越好,贝茜需要美美的睡上一觉,因此她要尽快赶回来。
约翰田里有N([2,1 000])个地标,并且每个地标都标上了唯一的号码,这些号码是从1~N的数字,1号表示谷仓,贝茜现在所在的苹果林的标识号码是N。已知牛在田里的T([1, 2 000])个道路耕作,这些道路是位于两个地标之间的双向通路。贝茜对自己认路的能力不是很自信,所以一旦她从某个地标出发,开始沿道路走时,她总会一直走到道路结束的地方(也就是下一个地标处)。请编写一个程序,帮助贝茜确定回到谷仓的最短路径,这里假设回到谷仓的路径必然存在。(来源,USACO)
【输入】本程序输入由两部分组成。第一部分即程序输入的第1行是两个整数T和N。输入的第二部分是由第2行到第T+1行组成,每行是由3个空格隔开的整数。前两个是地标的号码,第3个是该条道路的长度,其范围是1~100。
示例:
5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100
【输出】本程序输出的是一个整数,它表示贝茜从N号走到1号地标必须经过最短的路径,以上面的输入为例,此时需要的最短路径是90,可以知道贝茜所走的最短路径为5——4——3——2——1。
【分析与解答】求最短路径,可以用迪克斯特拉算法。
4. 棍子还原问题
【问题描述】乔治现有一些等长的绳子,并胡乱地对这些棍子进行分割,直到所有的棍子都不超过50个单位长度。现在他想把这些棍子都恢复到原始状态,但他忘记了自己原来究竟有多少根棍子及这些棍子的长度。请编写程序计算这些棍子的原来的长度的最小值,这里假设所有棍子的长度均为大于0的整数。(来源:Central Europe 1995)
【输入】该程序的输入应包括两个部分。第一部分是数据块,第二部分是结束标志。数据块部分一两行数据为一个单位,每个单位的第1行为分割后棍子的个数,并且这一数字不大于64,第2行数据为这些分割后棍子的具体长度值,这些长度值用空格隔开,最后键入0表示结束。
示例:
9
5 2 1 5 2 1 5 2 1
4
1 2 2 3
0
【输出】该程序的输出仅包括一行数据,它表示原来棍子的最小长度。以上面的输入为例,应该得到的输出为
6
5
【分析与解答】该题是一道搜索问题,可以考虑用深度优先搜索策略和剪枝策略相结合来解决。