PS:入坑一个半月的蒟蒻的第一篇题解有错误欢迎指出
题目描述
给定一个n个点m条边的有向图,图中可能存在重边和自环。
所有边的长度都是1,点的编号为1~n。
请你求出1号点到n号点的最短距离,如果从1号点无法走到n号点,输出-1。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含两个整数a和b,表示存在一条从a走到b的长度为1的边。
输出格式
输出一个整数,表示1号点到n号点的最短距离。
数据范围
1≤n,m≤105
样例
输入样例:
4 5
1 2
2 3
3 4
1 3
1 4
输出样例:
1
算法
用单链表储存树和图时,从每一个节点的头指针只能储存当前节点能到达的下一层的节点
宽度优先遍历没有进行递归所以每一次搜索都是以头结点指向的位置
例如 1->2 1->3 1->5 2->8 3->6 3->7
即
h[1]->5->3->2->-1;
h[2]->8->-1;
h[3]->7->6->-1;
宽度遍历和深度遍历的区别就是:深度优先遍历每搜一次就进入递归调用自身,使得搜索的节点的头指针发生变化即变成了指向当前节点的头指针,然后就变成了搜索此节点能到达的下一层。
宽度优先遍历没有进行递归也就是一直搜索当前节点能到达的下一层节点直到节点搜索完时再搜索下一节点 。
C++ 代码
#include<iostream>
usinga namespace std;
const int N=100010;
int n,tt=0,hh=0,m,idx=0;//头指针尾指针和插入的第几个数
int e[N],ne[N],q[N];
int d[N],h[N];//d[N]表示每个节点离1的距离
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;//插入操作
}
void bfs()
{
q[0]=1;
memset(d,-1,sizeof(d));
d[1]=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;//当前节点的根节点的距离加1
q[++tt]=j;//插入队列中
}
}
}
cout<<d[n]<<endl;
}
int main()
{
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
add(a,b);
}
bfs();
return 0;
}
6
大佬tql