描述
设计一个算法,试基于深度优先搜索判断以邻接表方式存储的有向图中是否存在由顶点vi到顶点vj的路径(i≠j)。
输入
多组数据,每组m+3数据行。第一行有两个数字n和m,代表有n个顶点和m条边。第二行有n个字符,代表n个顶点的编号。第三行到第m+2行每行有两个字符h和k,代表边依附的两个顶点。第m+3行有两个字符vi和vj,代表需要判断的两个顶点。当n和m都等于0时,输入结束。
输出
每组数据输出一行。若存在路径输出“YES”,反之输出“NO”。
数据结构定义:
邻接表的结构如下:
以题目提供的第一个输入为例:
abc
ab
bc
[头结点a]->[b]->NULL
[头结点b]->[c]->NULL
[头结点c]->NULL
//定义结点类型ANode:
typedef struct ANode {
char val;
ANode* next;
} ANode, *Alist;
//定义邻接表:
typedef struct AGraph {
unordered_map<char,Alist>List; //unordered_map:字典类型
int vnum, anum; //其中的边数量anum似乎没啥用
} AGraph;
邻接表的初始化与根据输入的创建:
void create(AGraph& AG, int vn, int an) {
AG.vnum = vn,AG.anum = an; //anum其实是用不到的
string vlist;cin>>vlist;
for(int i = 0;i < vn;i ++){
AG.List[vlist[i]] = new ANode; //unordered_map中,前者相当于数组的下标索引
AG.List[vlist[i]]->next = NULL; //索引类型char,数据类型Alist,这里不难理解
}
for(int i = 0;i < an;i ++){
string v2v;cin>>v2v; //v2v意思就是vertex to vertex,点到点
ANode *p = new ANode;
p->val = v2v[1]; //头插法,可以使用尾插法,不过需要找到链表尾部
p->next = AG.List[v2v[0]]->next;
AG.List[v2v[0]]->next = p;
}
}
深度优先搜索DFS和入口函数solution:
void DFS(AGraph& G,char vertex,unordered_map<char,bool>& visited,char targetV,bool &isFound){//bool值需要使用地址引用,不然的话传入的参数是个形参,无法在solution中发生改变
/*
在邻接表中进行深度优先的思路就是:
结点是否有->next?(例如[头结点a]->[b]->NULL)
--有:进入到->next结点(即b)
然后进入[头结点b]的深度优先
假设是到了[b]->NULL,于是递归会返回,进入到后面的[b]->next(也就是NULL)中
*/
visited[vertex] = true;
ANode* currNode = G.List[vertex]->next;
while(currNode){
char nextVertex = currNode->val;//注意,这里保存的不是下一个结点本身,而是结点索引
if(nextVertex == targetV){
isFound = true;
}
if(!visited[nextVertex]){
DFS(G,nextVertex,visited,targetV,isFound);
}
currNode = currNode->next;
}
}
void solution(AGraph& AG){//入口函数
char beginV,targetV;
cin>>beginV>>targetV;
unordered_map<char,bool>visited;
for(auto it = AG.List.begin();it != AG.List.end();it ++){
visited[it->first] = false;//visted经过初始化完成后,就是visited[a] or [b] or [c] = false
}
bool isFound = false;
DFS(AG,beginV,visited,targetV,isFound);
if(isFound){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
main函数:
int main() {
int vn, an;
cin >> vn >> an;
while (vn != 0 || an != 0) {
AGraph AG;
create(AG, vn, an);
solution(AG);
cin >> vn >> an;
}
return 0;
}
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef struct ANode {
char val;
ANode* next;
} ANode, *Alist;
typedef struct AGraph {
unordered_map<char,Alist>List;
int vnum, anum;
} AGraph;
void create(AGraph& AG, int vn, int an) {
AG.vnum = vn,AG.anum = an;
string vlist;cin>>vlist;
for(int i = 0;i < vn;i ++){
AG.List[vlist[i]] = new ANode;
AG.List[vlist[i]]->next = NULL;
}
for(int i = 0;i < an;i ++){
string v2v;cin>>v2v;
ANode *p = new ANode;
p->val = v2v[1];
p->next = AG.List[v2v[0]]->next;
AG.List[v2v[0]]->next = p;
}
}
void DFS(AGraph& G,char vertex,unordered_map<char,bool>& visited,char targetV,bool &isFound){
visited[vertex] = true;
ANode* currNode = G.List[vertex]->next;
while(currNode){
char nextVertex = currNode->val;
if(nextVertex == targetV){
isFound = true;
}
if(!visited[nextVertex]){
DFS(G,nextVertex,visited,targetV,isFound);
}
currNode = currNode->next;
}
}
void solution(AGraph& AG){
char beginV,targetV;
cin>>beginV>>targetV;
unordered_map<char,bool>visited;
for(auto it = AG.List.begin();it != AG.List.end();it ++){
visited[it->first] = false;
}
bool isFound = false;
DFS(AG,beginV,visited,targetV,isFound);
if(isFound){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
int main() {
int vn, an;
cin >> vn >> an;
while (vn != 0 || an != 0) {
AGraph AG;
create(AG, vn, an);
solution(AG);
cin >> vn >> an;
}
return 0;
}