一、思考与总结
1、本题是图的存储+(BFS)的结合
2、图的存储用邻接表
3、图的权值是(1)的时候,重边和环不用考虑。
4、所有长度都是(1),表示可以用(bfs)来求最短路,否则应该用迪杰斯特拉等算法来求图中的最短路径。
5、(bfs)需要记录的是出发点到当前点的距离,就是(d)数组,每次(d)要增加(1)。
6、一定要注意数组的初始化!!!!!
(1) memset(h,-1,sizeof h);
//数组的整体初始化为-1,这是链表结束循环的边界,缺少会(TLE)
(2) memset(d,-1,sizeof d);
//表示没有走过。
二、STL队列
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m;
//h[N]表示有N条单链表的头,e[M]代表每个节点的值,ne[M]代表每个节点的下一个节点号
int h[N], e[N << 1], ne[N << 1], idx;
int d[N];//距离
queue<int> q;
//树和图的存储
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int bfs() {
//1号结点入队列
q.push(1);
//1号结点到自己的距离是0
d[1] = 0;
//bfs
while (!q.empty()) {
int u = q.front();
q.pop();
//遍历链表
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (d[j] == -1) { //没走过
d[j] = d[u] + 1;
q.push(j);
}
}
}
//1号结点到n号结点的最短距离
return d[n];
}
int main() {
//输入优化
ios::sync_with_stdio(false);
//n个结点,m条边
cin >> n >> m;
//初始化为-1,头节点写成-1
memset(h, -1, sizeof h);
//设置所有距离为-1
memset(d, -1, sizeof d);
//读入数据
for (int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
add(a, b);
}
//输出
cout << bfs() << endl;
return 0;
}
三、数组模拟队列
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m;
//h[N]表示有N条单链表的头,e[M]代表每个节点的值,ne[M]代表每个节点的下一个节点号
int h[N], e[N << 1], ne[N << 1], idx;
int d[N];//距离
int q[N], hh, tt = -1;
//树和图的存储
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int bfs() {
q[++tt] = 1;
d[1] = 0; //第一节点的距离是0
while (hh <= tt) {
int t = q[hh++];
for (int i = h[t]; i != -1; i = ne[i]) {
int j = e[i];
if (d[j] == -1) { //没走过
d[j] = d[t] + 1;
q[++tt] = j;
}
}
}
return d[n];
}
int main() {
//输入优化
ios::sync_with_stdio(false);
//n个结点,m条边
cin >> n >> m;
//初始化为-1,头节点写成-1
memset(h, -1, sizeof h);
//设置所有距离为-1
memset(d, -1, sizeof d);
//读入数据
for (int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
add(a, b);
}
//输出
cout << bfs() << endl;
return 0;
}