蓝桥杯 - 网格寻路(图论 2013 国赛)

本文探讨了如何使用深度优先搜索(DFS)算法解决特定图论问题,即寻找图中长度为2的路径数量,同时确保这些路径在除去起始节点外不包含重复节点。通过构建邻接表而非邻接矩阵来优化空间复杂度,并提供了详细的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本题的主要问题是:
1、 输入的顶点数最大可能有1*10的4次方,如果用邻接矩阵表示,那么就要10000×10000大小的数组。明显是不行的。
最好还是要用邻接表(这里我用的是数组表示的邻接表)。
2、 很容易看出是求路径为2的路线有多少条,但是怎么判断是否合法?(合法:除了起始两个节点,其他的都不能相同,起始两个可以相同也可以不同)。
方法:dfs的每一次进行根据前面走过的判断,当前的节点A(前一个节点是C),其下一个节点B,不能和C相同。

代码:

#include<bits/stdc++.h>
using namespace std;
// int edgs[10001][10001]; //不太可能,这是第一个主要的问题
//要用邻接表表示(点&边)
//题目其实就是求路径为2的有几条(不管起始相同与否),但是要求中间的不能相同(尾部可以)
struct edge
{
    int x, y;//始末两点
    int next;
}edgs[20010];
int vexs[10005];//点表,值是由此点出发的第一条边
int vexNum  = 0, edgNum = 0, ans = 0,tot = 0;
void Add(int x,int y)
{
    int head = vexs[x];
    tot++;
    edgs[tot].x = x;
    edgs[tot].y = y;
    edgs[tot].next = head/*下一条边的下标*/;
    vexs[x] = tot;
}
void dfs(int x/*当前的*/,int pre/*前一个*/,int num)
{
    if(num == 3)
    {
        ans++;
        return;
    }
    else
    {
        for (int i = vexs[x]; i ;i = edgs[i].next)
        {
            int next = edgs[i].y;
            //i为下一个边的下标
            if(next!=pre)
            {
                dfs(next,x,num+1);
            }
        }
    }
}
int main()
{
    int x, y,i;
    scanf("%d %d",&vexNum,&edgNum);
    // vexNum = 5,edgNum = 6;
    for (int i = 1; i <= edgNum;i++)
    {
        scanf("%d%d",&x,&y);
        Add(x,y);
        Add(y,x);
    }
    for (int i = 1; i <= vexNum; i++)
    {
        dfs(i,0,0);
    }
    printf("%d",ans);
    return 0;
}
### 蓝桥杯网格寻路问题解析 蓝桥杯中的网格寻路问题是典型的图论问题之一,通常涉及计算特定条件下的路径数量。以下是对此类问题的解题思路以及示例代码。 #### 1. 图模型构建 此类问题可以抽象成一个无向图 \(G=(V,E)\),其中节点表示网络中的各个位置,边则代表两个节点之间的连通关系。对于题目中提到的数据包必须恰好被转发两次的要求,可以通过枚举中间节点来实现这一约束[^2]。 #### 2. 枚举中间节点 假设起点为 \(S\),终点为 \(T\),那么满足条件的路径形式应为 \(S \rightarrow X \rightarrow T\),其中 \(X\) 是某个中间节点。因此,我们可以分别预处理从 \(S\) 到所有其他节点的距离,以及从所有节点到 \(T\) 的距离。通过双重循环遍历所有的可能中间节点 \(X\) 来统计符合条件的路径数。 #### 3. 广度优先搜索(BFS) 由于需要精确控制步数,广度优先搜索是一种适合的方法。它能够逐层扩展并记录每一步的状态变化。具体来说,在 BFS 中维护当前所在的节点及其已经经过的跳转次数即可完成此任务。 下面给出基于上述方法的一个 Python 实现: ```python from collections import deque, defaultdict def count_paths(n, edges, start, end): graph = defaultdict(list) # 建立邻接表 for u, v in edges: graph[u].append(v) graph[v].append(u) def bfs(s, t): dist = [-1]*(n+1) # 初始化距离数组 q = deque([(s, 0)]) # 队列存储 (node, steps) while q: node, step = q.popleft() if node == t and step == 2: # 如果达到目标且正好两步,则返回成功 return True if step >= 2: continue # 只允许最多走两步 for neighbor in graph[node]: if dist[neighbor]==-1 or dist[neighbor]>step+1: dist[neighbor]=step+1 q.append((neighbor, step+1)) return False path_count = 0 for intermediate_node in range(1,n+1): # 尝试每一个作为中间节点的可能性 if bfs(start,intermediate_node) and bfs(intermediate_node,end): path_count +=1 return path_count # 测试样例 edges = [(1,2),(2,3),(3,4),(4,5)] print(count_paths(5, edges, 1, 5)) # 输出应该反映有多少种有效路径 ``` 以上程序实现了基本的功能需求,并考虑到了数据包需经由确切两次跳跃才能抵达最终目的地的情况。 #### §相关问题§ 1. 如何优化上述算法的时间复杂度? 2. 当前解决方案能否适用于加权图?如果能的话需要注意哪些地方调整? 3. 是否存在更高效的替代方案比如动态规划或者矩阵快速幂运算? 4. 对于大规模稀疏图场景下如何进一步提升性能表现? 5. 在实际应用环境中除了最短路径外还有哪些因素会影响路由决策过程?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值