​题目描述​

P5318 【深基18.例3】查找文献_dfs


P5318 【深基18.例3】查找文献_i++_02

请对这个图分别进行 DFS 和 BFS,并输出遍历结果。如果有很多篇文章可以参阅,请先看编号较小的那篇(因此你可能需要先排序)。
输入

8 9
1 2
1 3
1 4
2 5
2 6
3 7
4 7
4 8
7 8

输出

1 2 5 6 3 7 8 4 
1 2 3 4 5 6 7 8

思路:DFS+BFS+图的存储 这个题中在搜索过程中需要不断的判断两点之间的边是否存在,所以应该使用邻接矩阵,但由于数据量太多,所以邻接矩阵也是不行的.我们可以使用vector.然后用一种新的方法来存储图.

  1. 首先,我们用一个结构体vector(为了节省空间,咱用vector来存)存储每个边的起点和终点,然后用一个二维vector(也就是一个vector数组)存储边的信息。
  2. 我们用e[a][b]=c,来表示顶点a的第b条边是c号边。咱举个栗子,还是拿样例说吧:
8 9
1 2 //0号边(由于vector的下标是从0开始的,咱就“入乡随俗”,从0开始)
1 3 //1号边
1 4 //2号边
2 5 //3号边
2 6 //4号边
3 7 //5号边
4 7 //6号边
4 8 //7号边
7 8 //8号边

最后二维vector中的存储会如下所示:

0 1 2 //1号顶点连着0、1、2号边
3 4 //2号顶点连着3、4号边
5 //3号顶点连着5号边
6 7 //4号顶点连着6、7号边
//5号顶点没有边
//6号顶点没有边
8 //7号顶点连着8号边
//8号顶点没有边
  1. 别忘了题目要求:“如果有很多篇文章可以参阅,请先看编号较小的那篇”
    那就排序呗!咱们按照题目要求,如果起始点相同则先终点从小到大进行排列,如果起始点不同则起始点从小到大排列.(这里的理解可能有问题,看出来的兄弟,可以说说自己的想法)

参考代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000+10;
int n,m,vex[maxn],visited1[maxn],visited2[maxn],u2,v2;
struct edge{
int u,v;
edge(int u1,int v1):u(u1),v(v1){//构造方法
};
};
vector<edge> s;
vector<int> e[maxn];
bool cmp(edge X,edge Y){//用于排序
// if(X.v==Y.v){
// return X.u<Y.u;
// }else{
// return X.v < Y.v;
// }
if(X.u==Y.u){
return X.v < Y.v;
}else{
return X.u < Y.u;
}
}

void dfs(int x){
cout<<x<<" ";
visited1[x] = 1;
for(int i = 0; i < e[x].size(); i++){// i:代表e下表
int w = e[x][i];
if(!visited1[w])//没有被访问
{
dfs(w);
}
}
}

void bfs(int x){
queue<int> Q;
Q.push(x);
visited2[x] = 1;
while(!Q.empty()){
int temp = Q.front();
Q.pop();
cout<<temp<<" ";
for(int i = 0; i < e[temp].size(); i++){
int w = e[temp][i];
if(!visited2[w]){
Q.push(w);
visited2[w] = 1;
}
}
}
}

int main()
{
cin>>n>>m;
while(m--){
cin>>u2>>v2;
s.push_back(edge(u2,v2));//将边放到s中
}
sort(s.begin(),s.end(),cmp);//进行排序 按照终点从小到大进行排序,如果终点相同则按照起始点从 小到大进行排序 (后面)
// for(int i = 0; i < s.size(); i++){
// cout<<s[i].u<<"--"<<s[i].v<<endl;
// }
for(int i = 0;i<s.size(); i++) //vector 用s对邻接表进行初始化(这是一个由vector构成的邻接表)
{
e[s[i].u].push_back(s[i].v);
}
dfs(1);
cout<<endl;
bfs(1);
cout<<endl;
return 0;
}