题解:AcWing 847 图中点的层次

【题目来源】

AcWing:847. 图中点的层次 - AcWing题库

【题目描述】

给定一个\(n\)个点\(m\)条边的有向图,图中可能存在重边和自环。所有边的长度都是\(1\),点的编号为\(1\sim n\)。请你求出\(1\)号点到\(n\)号点的最短距离,如果从\(1\)号点无法走到\(n\)号点,输出\(-1\)

【输入】

第一行包含两个整数\(n\)\(m\)

接下来\(m\)行,每行包含两个整数\(a\)\(b\),表示存在一条从\(a\)走到\(b\)的长度为\(1\)的边。

【输出】

输出一个整数,表示\(1\)号点到\(n\)号点的最短距离。

【输入样例】

4 5
1 2 
2 3
3 4
1 3
1 4

【输出样例】

1

【算法标签】

《AcWing 847 图中点的层次》 #BFS#

【代码详解】

// 使用STL队列
#include <bits/stdc++.h>
using namespace std;

const int N = 100010;  // 节点最大数量
int n, m;  // n: 节点数量,m: 边数量
int h[N], e[N], ne[N], idx;  // 邻接表存储图,h: 头节点数组,e: 边终点数组,ne: 下一条边数组,idx: 边计数器
int d[N];  // 记录从起点到每个节点的距离
bool st[N];  // 记录节点是否被访问过
queue<int> q;  // BFS队列

// 添加一条有向边 a->b
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

// 广度优先搜索,返回从节点1到节点n的最短距离
int bfs()
{
    st[1] = true;  // 标记起点为已访问
    q.push(1);  // 起点入队
    memset(d, -1, sizeof(d));  // 初始化距离为-1(表示不可达)
    d[1] = 0;  // 起点距离为0
    
    while (!q.empty())
    {
        int t = q.front();  // 取出队首节点
        q.pop();
        
        // 遍历当前节点的所有邻接节点
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];  // 邻接节点编号
            if (!st[j])  // 如果邻接节点未被访问
            {
                st[j] = true;  // 标记为已访问
                d[j] = d[t] + 1;  // 更新距离
                q.push(j);  // 入队
            }
        }
    }
    return d[n];  // 返回到达节点n的距离
}

int main()
{
    cin >> n >> m;  // 读入节点数量和边数量
    memset(h, -1, sizeof(h));  // 初始化邻接表头节点
    
    // 读入边并建图
    for (int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
    }
    
    cout << bfs() << endl;  // 输出从1到n的最短距离
    return 0;
}
// 数据模拟队列
#include <bits/stdc++.h>
using namespace std;

const int N = 100010;  // 节点最大数量
int n, m;  // n: 节点数量,m: 边数量
int h[N], e[N], ne[N], idx;  // 邻接表存储图,h: 头节点数组,e: 边终点数组,ne: 下一条边数组,idx: 边计数器
int d[N], q[N];  // d: 记录从起点到每个节点的距离,q: 数组模拟队列

// 添加一条有向边 a->b
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

// 广度优先搜索,返回从节点1到节点n的最短距离
int bfs()
{
    int hh = 0, tt = 0;  // 队列头尾指针
    q[0] = 1;  // 起点入队
    memset(d, -1, sizeof(d));  // 初始化距离为-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];  // 返回到达节点n的距离
}

int main()
{
    cin >> n >> m;  // 读入节点数量和边数量
    memset(h, -1, sizeof(h));  // 初始化邻接表头节点
    
    // 读入边并建图
    for (int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
    }
    
    cout << bfs() << endl;  // 输出从1到n的最短距离
    return 0;
}

【运行结果】

4 5
1 2
2 3
3 4
1 3
1 4
1
posted @ 2026-02-19 15:20  团爸讲算法  阅读(6)  评论(0)    收藏  举报