O(n),n是边数。
边的权只有两种:0,1。
n个端点的无向图,编号范围[0,n)。Edges0表示{{n1,n2},...{n3,n4}}表示n1和n2,n3和n4之间有路联接。Edges1表示{{n1,n2},...{n3,n4}}表示n1和n2,n3和n4之间有损坏的路连接。要想让s和d之间至少有一条通道,最小需要维修多少条路。如果无法到达,请返回-1。可能有环,但无自环,重边,可能不联通。
可以用类似上章的思路,没损害的路加到pre中,损坏的路加到que中。距离相等的点,谁先谁后无所谓。需要维修的路入队的时候不能计算最短距离,因为不一定是最短边。改在入队计算最短距离,第一层循环记录最短距离。
- class CBFS1
- {
- public:
- CBFS1(vector
int>>& vNeiB0, vectorint>>& vNeiB1, int s) - {
- m_vDis.assign(vNeiB0.size(), -1);
- //m_vDis[s] = 0;
- queue<int> pre;
- pre.emplace(s);
- for (int i = 0; pre.size(); i++)
- {
- queue<int> dp;
- while (pre.size())
- {
- const int cur = pre.front();
- pre.pop();
- if (-1 != m_vDis[cur])
- {
- continue;
- }
- m_vDis[cur] = i;
- for (const auto next : vNeiB0[cur])
- {
- pre.emplace(next);
- }
-
- for (const auto next : vNeiB1[cur])
- {
- dp.emplace(next);
- }
- }
- dp.swap(pre);
- }
- }
- public:
- vector<int> m_vDis;
- };
#define CBFS CBFS1
class CDebugBFS : public CBFS
{
public:
using CBFS::CBFS;
void Assert(const vector
{
for (int i = 0; i < vDis.size(); i++)
{
assert(vDis[i] == m_vDis[i]);
}
}
};
struct CDebugParam
{
int n;
vector
vector
int s;
vector
};
int main()
{
vector
{6,{}, { {0,1},{1,2},{1,3},{2,4},{4,5},{3,5}},0,{0,1,2,2,3,3} },
{6,{{3,5}}, { {0,1},{1,2},{1,3},{2,4},{4,5}},0,{0,1,2,2,3,2} }
};
for (const auto& par : params)
{
auto vNeiB0 = EdgeToNeiBo(par.n, par.edges0);
auto vNeiB1 = EdgeToNeiBo(par.n, par.edges1);
CDebugBFS bfs(vNeiB0, vNeiB1,par.s);
bfs.Assert(par.dis);
}
}
魔塔经典问题,砸墙需要一个锄头,没墙的地方可以随便移动,如果用尽可能少的锄头到达目的地。许多游戏经过箭塔附件时,会遭到箭塔攻击。如何已最小的损坏通过箭塔。
| 当前状态 | 操作 | 新状态 |
| 空 | 处理结束 | |
| 首尾入队 | 一种最短距离 | |
| 一种最短距离 | 出队 | 状态不变或变为空 |
| 队首入队 | 一种最短距离或两种最短距离 | |
| 队尾入队 | 一种最短距离或两种最短距离 | |
| 二种最短距离 | 出队 | 状态不变或变为一种最短距离 |
| 队首入队 | 两种最短距 | |
| 队尾入队 | 两种最短距 | |
- class C01BFSDis
- {
- public:
- C01BFSDis(vector
int>>& vNeiB0, vectorint>>& vNeiB1, int s) - {
- m_vDis.assign(vNeiB0.size(), -1);
- std::deque
int,int>> que; - que.emplace_back(s,0);
- while (que.size())
- {
- auto it = que.front();
- const int cur = it.first;
- const int dis = it.second;
- que.pop_front();
- if (-1 != m_vDis[cur])
- {
- continue;
- }
- m_vDis[cur] = it.second;
- for (const auto next : vNeiB0[cur])
- {
- if (-1 != m_vDis[next])
- {
- continue;
- }
- que.emplace_front(next,dis);
-
- }
-
- for (const auto next : vNeiB1[cur])
- {
- if (-1 != m_vDis[next])
- {
- continue;
- }
- que.emplace_back(next, dis+1);
- }
- }
- }
- public:
- vector<int> m_vDis;
- };
源码下载:
https://download.csdn.net/download/he_zhidan/88383828

如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。
https://edu.csdn.net/course/detail/38771
我的其它课程
https://edu.csdn.net/lecturer/6176
win7 VS2019 C++17 或Win10 VS2022 Ck++17
算法精讲《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
| 作者人生格言 |
| 有所得,以墨记之,故曰墨家 |
| 闻缺陷则喜。问题发现得越早,越给老板省钱。 |
| 算法是程序的灵魂 |
![]()