单源无权最短路径举例——字梯问题
  1![]() /*
/*
2![]() 最短路径的一个举例:
最短路径的一个举例:
3![]()
4![]() 问题描述:在字梯游戏中,每一个词语都是通过将字梯的前一个词改变一个字母形成的。
问题描述:在字梯游戏中,每一个词语都是通过将字梯的前一个词改变一个字母形成的。
5![]() 例如,我们可以通过一系列的单字母替换将zero转换成five:zero, hero, here, hire, fire, five。
例如,我们可以通过一系列的单字母替换将zero转换成five:zero, hero, here, hire, fire, five。
6![]()
7![]() 这个是一个无权最短路径问题,每个词语是个顶点,如果两个顶点可以通过一个字母的替换相互转换的话,
这个是一个无权最短路径问题,每个词语是个顶点,如果两个顶点可以通过一个字母的替换相互转换的话,
8![]() 这两个顶点就有一个双向的边。
这两个顶点就有一个双向的边。
9![]()
10![]() 首先,我们要从一个字典中生成这么一个图:使用STL中的map,其中键是单词(string),
首先,我们要从一个字典中生成这么一个图:使用STL中的map,其中键是单词(string),
11![]() 值是一个通过此单词一次变换能够得到的单词的集合vector<string>。
值是一个通过此单词一次变换能够得到的单词的集合vector<string>。
12![]() 问题的关键在于:如何从一个包含89000个单词的词组来构造map。
问题的关键在于:如何从一个包含89000个单词的词组来构造map。
13![]() 可以用蛮力法,但是时间太慢,所有单词之间都要比较。一个优化是:避免比较长度不同的单词。
可以用蛮力法,但是时间太慢,所有单词之间都要比较。一个优化是:避免比较长度不同的单词。
14![]() 这个可以通过将单词按照长度先分组来做到。
这个可以通过将单词按照长度先分组来做到。
15![]()
16![]() 一个方法是:对每个相同长度的数组用蛮力法。
一个方法是:对每个相同长度的数组用蛮力法。
17![]() 另一个方法是:附加一个map,其中的键是一个反映单词长度的int,值是所有的具有这个长度的单词集合。
另一个方法是:附加一个map,其中的键是一个反映单词长度的int,值是所有的具有这个长度的单词集合。
18![]() 思想还是同上。
思想还是同上。
19![]() 第三个方法是:使用附加map。将单词按照长度分组,对每个组分别操作。例如对长度为4的小组。
第三个方法是:使用附加map。将单词按照长度分组,对每个组分别操作。例如对长度为4的小组。
20![]() 对每个长度为4的单词删除第一个字母,保留剩下的三个字母的样本,生成一个map,其中的键是这个样本,
对每个长度为4的单词删除第一个字母,保留剩下的三个字母的样本,生成一个map,其中的键是这个样本,
21![]() 值是所有的有这个样本单词的vector。例如单词"wine",去掉'w'生成样本"ine",则样本"ine"对应的
值是所有的有这个样本单词的vector。例如单词"wine",去掉'w'生成样本"ine",则样本"ine"对应的
22![]() vector是"dine", "fine", "wine", "nine"
vector是"dine", "fine", "wine", "nine"![]()
![]() .,样本"oot"对应:boot, foot, hoot, loot
.,样本"oot"对应:boot, foot, hoot, loot![]() ..最后的这个map的值(vector)就是
..最后的这个map的值(vector)就是
23![]() 一组单词,其中每个单词都能够通过一个字符的替换生成其他的单词。
一组单词,其中每个单词都能够通过一个字符的替换生成其他的单词。
24![]() */
*/
25![]()
26![]() #include <iostream>
#include <iostream>
27![]() #include <sstream>
#include <sstream>
28![]() #include <algorithm>
#include <algorithm>
29![]() #include <string>
#include <string>
30![]() #include <map>
#include <map>
31![]() #include <set>
#include <set>
32![]() #include <list>
#include <list>
33![]() #include <stack>
#include <stack>
34![]() #include <queue>
#include <queue>
35![]() #include <cctype>
#include <cctype>
36![]() #include <vector>
#include <vector>
37![]() #include <bitset>
#include <bitset>
38![]() #include <cmath>
#include <cmath>
39![]() //#include <hash_map>
//#include <hash_map>
40![]()
41![]() #define FORR(i, a, b) for(int i = a; i < b; ++i)
#define FORR(i, a, b) for(int i = a; i < b; ++i)
42![]() #define BE(x) x.begin(),x.end()
#define BE(x) x.begin(),x.end()
43![]() #define MP(a, b) make_pair(a, b)
#define MP(a, b) make_pair(a, b)
44![]()
45![]() using namespace std;
using namespace std;
46![]() //using namespace stdex;
//using namespace stdex;
47![]()
48![]() typedef vector<string> VS;
typedef vector<string> VS;
49![]() typedef vector<int> VI;
typedef vector<int> VI;
50![]()
51![]() //words是所有的单词
//words是所有的单词
52![]() map<string, VS> computerAdjacentWords(const VS& words)
map<string, VS> computerAdjacentWords(const VS& words)
53![]() {
{
54![]() map<string, VS> adjWords;
    map<string, VS> adjWords;
55![]() map<int, VS> wordsByLength;
    map<int, VS> wordsByLength;
56![]()
57![]() //按长度分组
    //按长度分组
58![]() for (int i = 0; i < words.size(); i++)
    for (int i = 0; i < words.size(); i++)
59![]() {
    {
60![]() wordsByLength[words[i].length()].push_back(words[i]);
        wordsByLength[words[i].length()].push_back(words[i]);
61![]() }
    }
62![]() map<int, VS>::const_iterator itr;
    map<int, VS>::const_iterator itr;
63![]() //对每个分组操作
    //对每个分组操作
64![]() for (itr = wordsByLength.begin(); itr != wordsByLength.end(); ++itr)
    for (itr = wordsByLength.begin(); itr != wordsByLength.end(); ++itr)
65![]() {
    {
66![]() const VS& groupsWords = itr->second;
        const VS& groupsWords = itr->second;
67![]() int groupNum = itr->first;
        int groupNum = itr->first;
68![]()
69![]() //操作每个组中的每个位置
        //操作每个组中的每个位置
70![]() for (int i = 0; i < groupNum; i++)
        for (int i = 0; i < groupNum; i++)
71![]() {
        {
72![]() //形如:"ine" -> "fine", "wine", "nine"
            //形如:"ine" -> "fine", "wine", "nine"![]() .
.
73![]() map<string, VS> repToWord;
            map<string, VS> repToWord;
74![]()
75![]() for (int j = 0; j < groupsWords.size(); j++)
            for (int j = 0; j < groupsWords.size(); j++)
76![]() {
            {
77![]() string rep = groupsWords[j];
                string rep = groupsWords[j];
78![]() rep.erase(i, 1);
                rep.erase(i, 1);
79![]() //map的无重复性就是好,而且如果没有对应的可以直接新建一个
                //map的无重复性就是好,而且如果没有对应的可以直接新建一个
80![]() //wine加到ine中,fine也加到ine中
                //wine加到ine中,fine也加到ine中
81![]() //wine也加到wne中
                //wine也加到wne中
82![]() repToWord[rep].push_back(groupsWords[j]);
                repToWord[rep].push_back(groupsWords[j]);
83![]() }
            }
84![]()
85![]() // 然后查找map中的值不止一个单词的(就是有像wine,fine这种)
            // 然后查找map中的值不止一个单词的(就是有像wine,fine这种)
86![]() map<string, VS>::const_iterator itr2;
            map<string, VS>::const_iterator itr2;
87![]() for (itr2 = repToWord.begin(); itr2 != repToWord.end(); ++itr2)
            for (itr2 = repToWord.begin(); itr2 != repToWord.end(); ++itr2)
88![]() {
            {
89![]() const VS& clique = itr2->second;
                const VS& clique = itr2->second;
90![]() if (clique.size() >= 2)
                if (clique.size() >= 2)
91![]() {
                {
92![]() for (int p = 0; p < clique.size(); p++)
                    for (int p = 0; p < clique.size(); p++)
93![]() {
                    {
94![]() for (int q = p + 1; q < clique.size(); q++)
                        for (int q = p + 1; q < clique.size(); q++)
95![]() {
                        {
96![]() adjWords[clique[p]].push_back(clique[q]);
                            adjWords[clique[p]].push_back(clique[q]);
97![]() adjWords[clique[q]].push_back(clique[p]);
                            adjWords[clique[q]].push_back(clique[p]);
98![]() }
                        }
99![]() }
                    }
100![]() }
                }
101![]() }
            }
102![]() }
        }
103![]() }
    }
104![]() return adjWords;
    return adjWords;
105![]() }
}
106![]()
107![]() /*
/*
108![]() 下面就要使用单元无权最短路径算法了:
下面就要使用单元无权最短路径算法了:
109![]() 上面生成的map就相当是一个邻接链表的图表示:
上面生成的map就相当是一个邻接链表的图表示:
110![]() 一个节点和所有与它相连的节点集合。
一个节点和所有与它相连的节点集合。
111![]() 由于,单源无权最短路径算法只能给出每个节点在路径中的前驱节点,所以,
由于,单源无权最短路径算法只能给出每个节点在路径中的前驱节点,所以,
112![]() 这里返回的map<string,string>值就是最短路径中每个节点的相应前驱节点,而map中所有的键就是
这里返回的map<string,string>值就是最短路径中每个节点的相应前驱节点,而map中所有的键就是
113![]() 最短路径中的所有节点。例如:将zero转换成five:zero, hero, here, hire, fire, five,则,
最短路径中的所有节点。例如:将zero转换成five:zero, hero, here, hire, fire, five,则,
114![]() findChain返回的map<string,string>previousWord就是previousWord[five] = fire, previousWord[here] = hero。
findChain返回的map<string,string>previousWord就是previousWord[five] = fire, previousWord[here] = hero。
115![]() 注意:这里是找到从zero出发到所有节点的路径(中节点的前驱集合,所以没有second参数)
注意:这里是找到从zero出发到所有节点的路径(中节点的前驱集合,所以没有second参数)
116![]() */
*/
117![]() map<string, string> findChain(const map<string, VS> & adjacentWords, const string& first)
map<string, string> findChain(const map<string, VS> & adjacentWords, const string& first)
118![]() {
{
119![]() map<string, string> previousWord;
    map<string, string> previousWord;
120![]() queue<string> q;
    queue<string> q;
121![]()
122![]() q.push(first);
    q.push(first);
123![]() while (!q.empty())
    while (!q.empty())
124![]() {
    {
125![]() string current = q.front();
        string current = q.front();
126![]() q.pop();
        q.pop();
127![]()
128![]() map<string, VS>::const_iterator itr;
        map<string, VS>::const_iterator itr;
129![]() itr = adjacentWords.find(current);
        itr = adjacentWords.find(current);
130![]()
131![]() const VS& adj = itr->second;
        const VS& adj = itr->second;
132![]() for (int i =0; i < adj.size(); i++)
        for (int i =0; i < adj.size(); i++)
133![]() {
        {
134![]() if (previousWord[adj[i]] == "")
            if (previousWord[adj[i]] == "")
135![]() {
            {
136![]() previousWord[adj[i]] = current;
                previousWord[adj[i]] = current;
137![]() q.push(adj[i]);
                q.push(adj[i]);
138![]() }
            }
139![]() }
        }
140![]() }
    }
141![]() previousWord[first] = "";
    previousWord[first] = "";
142![]()
143![]() return previousWord;
    return previousWord;
144![]() }
}
145![]()
146![]() VS getChainFromPrevMap(const map<string, string>& previous, const string& second)
VS getChainFromPrevMap(const map<string, string>& previous, const string& second)
147![]() {
{
148![]() VS result;
    VS result;
149![]() //类型转换,因为操作符[]不能用在不可变的map中
    //类型转换,因为操作符[]不能用在不可变的map中
150![]() map<string, string>& prev = const_cast<map<string, string> &> (previous);
    map<string, string>& prev = const_cast<map<string, string> &> (previous);
151![]()
152![]() for (string current = second; current != ""; current = prev[current])
    for (string current = second; current != ""; current = prev[current])
153![]() result.push_back(current);
        result.push_back(current);
154![]()
155![]() reverse(result.begin(), result.end());
    reverse(result.begin(), result.end());
156![]()
157![]() return result;
    return result;
158![]() }
}
159![]()
160![]() int main()
int main()
161![]() {
{
162![]() string a[] = {"five", "hero", "boyfriend", "james", "zero", "good", "hire", "thank", "fire",
    string a[] = {"five", "hero", "boyfriend", "james", "zero", "good", "hire", "thank", "fire", 
163![]() "here", "pen", "ccbb", "greatman", "come", "great", "greet", "gold", "glad"};
        "here", "pen", "ccbb", "greatman", "come", "great", "greet", "gold", "glad"};
164![]() VS input(a, a+18);
    VS input(a, a+18);
165![]() string first("zero"), second("five");
    string first("zero"), second("five");
166![]()
167![]() //先构造一个图
    //先构造一个图
168![]() map<string, VS> adjWords = computerAdjacentWords(input);
    map<string, VS> adjWords = computerAdjacentWords(input);
169![]()
170![]() //再构造某个节点到所有节点最短路径中先驱集合
    //再构造某个节点到所有节点最短路径中先驱集合
171![]() map<string, string> previousWords = findChain(adjWords, first);
    map<string, string> previousWords = findChain(adjWords, first);
172![]()
173![]() //在找出到某个终点的最短路径
    //在找出到某个终点的最短路径
174![]() VS result = getChainFromPrevMap(previousWords, second);
    VS result = getChainFromPrevMap(previousWords, second);
175![]()
176![]() FORR(i, 0, result.size())
    FORR(i, 0, result.size())
177![]() {
    {
178![]() cout << result[i] << " ";
        cout << result[i] << " ";
179![]() }
    }
180![]() cout << endl;
    cout << endl;
181![]()
182![]() return 0;
    return 0;
183![]() }
}
 /*
/*2
 最短路径的一个举例:
最短路径的一个举例:3

4
 问题描述:在字梯游戏中,每一个词语都是通过将字梯的前一个词改变一个字母形成的。
问题描述:在字梯游戏中,每一个词语都是通过将字梯的前一个词改变一个字母形成的。5
 例如,我们可以通过一系列的单字母替换将zero转换成five:zero, hero, here, hire, fire, five。
例如,我们可以通过一系列的单字母替换将zero转换成five:zero, hero, here, hire, fire, five。6

7
 这个是一个无权最短路径问题,每个词语是个顶点,如果两个顶点可以通过一个字母的替换相互转换的话,
这个是一个无权最短路径问题,每个词语是个顶点,如果两个顶点可以通过一个字母的替换相互转换的话,8
 这两个顶点就有一个双向的边。
这两个顶点就有一个双向的边。9

10
 首先,我们要从一个字典中生成这么一个图:使用STL中的map,其中键是单词(string),
首先,我们要从一个字典中生成这么一个图:使用STL中的map,其中键是单词(string),11
 值是一个通过此单词一次变换能够得到的单词的集合vector<string>。
值是一个通过此单词一次变换能够得到的单词的集合vector<string>。12
 问题的关键在于:如何从一个包含89000个单词的词组来构造map。
问题的关键在于:如何从一个包含89000个单词的词组来构造map。13
 可以用蛮力法,但是时间太慢,所有单词之间都要比较。一个优化是:避免比较长度不同的单词。
可以用蛮力法,但是时间太慢,所有单词之间都要比较。一个优化是:避免比较长度不同的单词。14
 这个可以通过将单词按照长度先分组来做到。
这个可以通过将单词按照长度先分组来做到。15

16
 一个方法是:对每个相同长度的数组用蛮力法。
一个方法是:对每个相同长度的数组用蛮力法。17
 另一个方法是:附加一个map,其中的键是一个反映单词长度的int,值是所有的具有这个长度的单词集合。
另一个方法是:附加一个map,其中的键是一个反映单词长度的int,值是所有的具有这个长度的单词集合。18
 思想还是同上。
思想还是同上。19
 第三个方法是:使用附加map。将单词按照长度分组,对每个组分别操作。例如对长度为4的小组。
第三个方法是:使用附加map。将单词按照长度分组,对每个组分别操作。例如对长度为4的小组。20
 对每个长度为4的单词删除第一个字母,保留剩下的三个字母的样本,生成一个map,其中的键是这个样本,
对每个长度为4的单词删除第一个字母,保留剩下的三个字母的样本,生成一个map,其中的键是这个样本,21
 值是所有的有这个样本单词的vector。例如单词"wine",去掉'w'生成样本"ine",则样本"ine"对应的
值是所有的有这个样本单词的vector。例如单词"wine",去掉'w'生成样本"ine",则样本"ine"对应的22
 vector是"dine", "fine", "wine", "nine"
vector是"dine", "fine", "wine", "nine"
 .,样本"oot"对应:boot, foot, hoot, loot
.,样本"oot"对应:boot, foot, hoot, loot ..最后的这个map的值(vector)就是
..最后的这个map的值(vector)就是23
 一组单词,其中每个单词都能够通过一个字符的替换生成其他的单词。
一组单词,其中每个单词都能够通过一个字符的替换生成其他的单词。24
 */
*/25

26
 #include <iostream>
#include <iostream>27
 #include <sstream>
#include <sstream>28
 #include <algorithm>
#include <algorithm>29
 #include <string>
#include <string>30
 #include <map>
#include <map>31
 #include <set>
#include <set>32
 #include <list>
#include <list>33
 #include <stack>
#include <stack>34
 #include <queue>
#include <queue>35
 #include <cctype>
#include <cctype>36
 #include <vector>
#include <vector>37
 #include <bitset>
#include <bitset>38
 #include <cmath>
#include <cmath>39
 //#include <hash_map>
//#include <hash_map>40

41
 #define FORR(i, a, b) for(int i = a; i < b; ++i)
#define FORR(i, a, b) for(int i = a; i < b; ++i)42
 #define BE(x) x.begin(),x.end()
#define BE(x) x.begin(),x.end()43
 #define MP(a, b) make_pair(a, b)
#define MP(a, b) make_pair(a, b)44

45
 using namespace std;
using namespace std;46
 //using namespace stdex;
//using namespace stdex;47

48
 typedef vector<string> VS;
typedef vector<string> VS;49
 typedef vector<int> VI;
typedef vector<int> VI;50

51
 //words是所有的单词
//words是所有的单词52
 map<string, VS> computerAdjacentWords(const VS& words)
map<string, VS> computerAdjacentWords(const VS& words)53
 {
{54
 map<string, VS> adjWords;
    map<string, VS> adjWords;55
 map<int, VS> wordsByLength;
    map<int, VS> wordsByLength;56

57
 //按长度分组
    //按长度分组58
 for (int i = 0; i < words.size(); i++)
    for (int i = 0; i < words.size(); i++)59
 {
    {60
 wordsByLength[words[i].length()].push_back(words[i]);
        wordsByLength[words[i].length()].push_back(words[i]);61
 }
    }62
 map<int, VS>::const_iterator itr;
    map<int, VS>::const_iterator itr;63
 //对每个分组操作
    //对每个分组操作64
 for (itr = wordsByLength.begin(); itr != wordsByLength.end(); ++itr)
    for (itr = wordsByLength.begin(); itr != wordsByLength.end(); ++itr)65
 {
    {66
 const VS& groupsWords = itr->second;
        const VS& groupsWords = itr->second;67
 int groupNum = itr->first;
        int groupNum = itr->first;68

69
 //操作每个组中的每个位置
        //操作每个组中的每个位置70
 for (int i = 0; i < groupNum; i++)
        for (int i = 0; i < groupNum; i++)71
 {
        {72
 //形如:"ine" -> "fine", "wine", "nine"
            //形如:"ine" -> "fine", "wine", "nine" .
.73
 map<string, VS> repToWord;
            map<string, VS> repToWord;74

75
 for (int j = 0; j < groupsWords.size(); j++)
            for (int j = 0; j < groupsWords.size(); j++)76
 {
            {77
 string rep = groupsWords[j];
                string rep = groupsWords[j];78
 rep.erase(i, 1);
                rep.erase(i, 1);79
 //map的无重复性就是好,而且如果没有对应的可以直接新建一个
                //map的无重复性就是好,而且如果没有对应的可以直接新建一个80
 //wine加到ine中,fine也加到ine中
                //wine加到ine中,fine也加到ine中81
 //wine也加到wne中
                //wine也加到wne中82
 repToWord[rep].push_back(groupsWords[j]);
                repToWord[rep].push_back(groupsWords[j]);83
 }
            }84

85
 // 然后查找map中的值不止一个单词的(就是有像wine,fine这种)
            // 然后查找map中的值不止一个单词的(就是有像wine,fine这种)86
 map<string, VS>::const_iterator itr2;
            map<string, VS>::const_iterator itr2;87
 for (itr2 = repToWord.begin(); itr2 != repToWord.end(); ++itr2)
            for (itr2 = repToWord.begin(); itr2 != repToWord.end(); ++itr2)88
 {
            {89
 const VS& clique = itr2->second;
                const VS& clique = itr2->second;90
 if (clique.size() >= 2)
                if (clique.size() >= 2)91
 {
                {92
 for (int p = 0; p < clique.size(); p++)
                    for (int p = 0; p < clique.size(); p++)93
 {
                    {94
 for (int q = p + 1; q < clique.size(); q++)
                        for (int q = p + 1; q < clique.size(); q++)95
 {
                        {96
 adjWords[clique[p]].push_back(clique[q]);
                            adjWords[clique[p]].push_back(clique[q]);97
 adjWords[clique[q]].push_back(clique[p]);
                            adjWords[clique[q]].push_back(clique[p]);98
 }
                        }99
 }
                    }100
 }
                }101
 }
            }102
 }
        }103
 }
    }104
 return adjWords;
    return adjWords;105
 }
}106

107
 /*
/*108
 下面就要使用单元无权最短路径算法了:
下面就要使用单元无权最短路径算法了:109
 上面生成的map就相当是一个邻接链表的图表示:
上面生成的map就相当是一个邻接链表的图表示:110
 一个节点和所有与它相连的节点集合。
一个节点和所有与它相连的节点集合。111
 由于,单源无权最短路径算法只能给出每个节点在路径中的前驱节点,所以,
由于,单源无权最短路径算法只能给出每个节点在路径中的前驱节点,所以,112
 这里返回的map<string,string>值就是最短路径中每个节点的相应前驱节点,而map中所有的键就是
这里返回的map<string,string>值就是最短路径中每个节点的相应前驱节点,而map中所有的键就是113
 最短路径中的所有节点。例如:将zero转换成five:zero, hero, here, hire, fire, five,则,
最短路径中的所有节点。例如:将zero转换成five:zero, hero, here, hire, fire, five,则,114
 findChain返回的map<string,string>previousWord就是previousWord[five] = fire, previousWord[here] = hero。
findChain返回的map<string,string>previousWord就是previousWord[five] = fire, previousWord[here] = hero。115
 注意:这里是找到从zero出发到所有节点的路径(中节点的前驱集合,所以没有second参数)
注意:这里是找到从zero出发到所有节点的路径(中节点的前驱集合,所以没有second参数)116
 */
*/117
 map<string, string> findChain(const map<string, VS> & adjacentWords, const string& first)
map<string, string> findChain(const map<string, VS> & adjacentWords, const string& first)118
 {
{119
 map<string, string> previousWord;
    map<string, string> previousWord;120
 queue<string> q;
    queue<string> q;121

122
 q.push(first);
    q.push(first);123
 while (!q.empty())
    while (!q.empty())124
 {
    {125
 string current = q.front();
        string current = q.front();126
 q.pop();
        q.pop();127

128
 map<string, VS>::const_iterator itr;
        map<string, VS>::const_iterator itr;129
 itr = adjacentWords.find(current);
        itr = adjacentWords.find(current);130

131
 const VS& adj = itr->second;
        const VS& adj = itr->second;132
 for (int i =0; i < adj.size(); i++)
        for (int i =0; i < adj.size(); i++)133
 {
        {134
 if (previousWord[adj[i]] == "")
            if (previousWord[adj[i]] == "")135
 {
            {136
 previousWord[adj[i]] = current;
                previousWord[adj[i]] = current;137
 q.push(adj[i]);
                q.push(adj[i]);138
 }
            }139
 }
        }140
 }
    }141
 previousWord[first] = "";
    previousWord[first] = "";142

143
 return previousWord;
    return previousWord;144
 }
}145

146
 VS getChainFromPrevMap(const map<string, string>& previous, const string& second)
VS getChainFromPrevMap(const map<string, string>& previous, const string& second)147
 {
{148
 VS result;
    VS result;149
 //类型转换,因为操作符[]不能用在不可变的map中
    //类型转换,因为操作符[]不能用在不可变的map中150
 map<string, string>& prev = const_cast<map<string, string> &> (previous);
    map<string, string>& prev = const_cast<map<string, string> &> (previous);151

152
 for (string current = second; current != ""; current = prev[current])
    for (string current = second; current != ""; current = prev[current])153
 result.push_back(current);
        result.push_back(current);154

155
 reverse(result.begin(), result.end());
    reverse(result.begin(), result.end());156

157
 return result;
    return result;158
 }
}159

160
 int main()
int main()161
 {
{162
 string a[] = {"five", "hero", "boyfriend", "james", "zero", "good", "hire", "thank", "fire",
    string a[] = {"five", "hero", "boyfriend", "james", "zero", "good", "hire", "thank", "fire", 163
 "here", "pen", "ccbb", "greatman", "come", "great", "greet", "gold", "glad"};
        "here", "pen", "ccbb", "greatman", "come", "great", "greet", "gold", "glad"};164
 VS input(a, a+18);
    VS input(a, a+18);165
 string first("zero"), second("five");
    string first("zero"), second("five");166

167
 //先构造一个图
    //先构造一个图168
 map<string, VS> adjWords = computerAdjacentWords(input);
    map<string, VS> adjWords = computerAdjacentWords(input);169

170
 //再构造某个节点到所有节点最短路径中先驱集合
    //再构造某个节点到所有节点最短路径中先驱集合171
 map<string, string> previousWords = findChain(adjWords, first);
    map<string, string> previousWords = findChain(adjWords, first);172

173
 //在找出到某个终点的最短路径
    //在找出到某个终点的最短路径174
 VS result = getChainFromPrevMap(previousWords, second);
    VS result = getChainFromPrevMap(previousWords, second);175

176
 FORR(i, 0, result.size())
    FORR(i, 0, result.size())177
 {
    {178
 cout << result[i] << " ";
        cout << result[i] << " ";179
 }
    }180
 cout << endl;
    cout << endl;181

182
 return 0;
    return 0;183
 }
} 
                     
                    
                 
                    
                
 

 
     
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号