前言
本系列是我学习完大佬的方法后,为了蓝桥杯前几天可以快速过一遍所做,所以部分内容会很简洁。如果能够帮助到你,我也会很开心!!!
最短路径(单源最短路)
Floyd(正权图)
核心思想:通过新加的点来不断更新两点之间的最短距离
void floyd()
{
for (int k = 1; k <= n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
dp[i][j] = min(d[i][j], d[i][k] + d[k][j]);//最短距离
}
最小生成树
Prim 算法
步骤:从初始节点开始,逐步选择与当前生成树已经相连的所有边中权值最小的边
Kruskal算法
步骤:不断选择权值最小的边
需要用到的其他知识:并查集
并查集核心操作:
1.合并
p[root(a)] = root(b);
2.路径压缩:
int root(int x)
{
if (p[x] != x) p[x] = root(p[x]);//如果现在的点不是根节点,就继续向上遍历
return p[x];
}
如果它不等于根,就继续向上寻找根
代码思想:
先将所有的边按从小到大排序
然后遍历所有的边,如果没有连通,就连起来
拓扑序列
常用题目:关键路径
一般借助于邻接表,使用类似BFS实现处理每个点的入度,在读入边的时候处理
拓扑排序的解题关键:维护一个入度为0的路径
代码思想:
先把入度为0的点加入队列,然后取出队头的点,开始处理边,处理完成当入度为0时,说明已经y的所有入点已经全部完成
DFS序
先计入该节点进入的顺序,然后再看看他现在是否等于他的父亲,如果不等于的话就继续遍历他的孩子
void dfs(int now, int fa)
{
in[now] = ++cnt;//进入节点的顺序
for (int i = 0; i < n; i++)
{
if(edge[now]!=fa)//如果不等于父亲的话,就继续遍历儿子
dfs(edge[i],now)
}
out[now] = cnt;//出节点的顺序
}
最近共同祖先
倍增法
代码思想:先比较一下高度,然后进入循环,先遍历更深的点x,x逐渐往上走,等到高度x=y的时候,就可以共同遍历,判断两者是否会向上遍历到同一点,如果没有,继续向上遍历,知道遍历到一个点,此时的点就是最近共同祖先