【整理】基础图论模板题及知识点汇讲

本文整理了图论中的基础模板题及重要知识点,包括拓扑排序、最小生成树(Kruskal算法、Prim算法)、最短路径问题(Dijkstra算法、Floyed算法、SPFA算法)、有向图的连通性(Tarjan算法)等。通过实例解析和代码展示,帮助读者理解和掌握这些图论概念。同时,文章提供了错误和疏漏的反馈渠道,鼓励读者积极参与讨论与反馈。
摘要由CSDN通过智能技术生成

有兴趣的朋友可以去我的洛谷博客康康哦qwq

本篇文章洛谷博客传送门
我的博客总版传送门

特别特别感谢:

lmpp大佬牺牲自己宝贵时间,为我没有脾气的耐心讲解。

lmpp大佬的博客:墙裂建议进去康一康!

还有gmq、gbf同学,感谢你们的鼓励与支持!!
did教给我知识真是太强了!!

没有他们就没有这篇博客,我也会比现在蒻上 i n f inf inf倍。


提示:

本博客公开, 但“例题部分”仅记录的是本人认为较有意义添加的题或者是本人的知识盲区。 我会以知识点为经,算法为纬,在知识点开头加入模板题并附有代码,有的时候会写一点小提示,即 tips: \mathfrak\color{CornflowerBlue}\colorbox{Lavender}{tips:} tips:

在我自己掌握特别不好的题目/知识点旁会加以 ! \color{Red}\colorbox{Yellow}{!} 的标记。

所有题号以BSOJ为准。

有什么错误纰漏的直接QQ+洛谷私信+讨论区留言,我真的超级需要您的反馈的qwq。

希望能您能从这份清单中找到您的一些知识漏洞并把他们补起来!


更新信息

2020.3.29 1.0版本,开始新的篇章。知识点记录至拓扑排序模板题。

2020.3.30 && 2020.3.31 2.0版本,爆肝完所有知识点。


拓扑排序:

1462 拓扑排序

tips1: \mathfrak\color{CornflowerBlue}\colorbox{Lavender}{tips1:} tips1:

拓扑排序的基本知识:

  • 在图论中,拓扑排序是一个有向无环图(DAG)的所有顶点的线性序列,该序列必须满足下面两个条件:

    1. 每个顶点出现且只出现一次。
    2. 若存在一条从顶点A到顶点B的路径,那么在序列中顶点A出现在顶点B的前面。
  • 有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说。 [ 1 ] ^{[1]} [1]

  • 拓扑排序的操作方法:

    1. 从DAG图中选择一个 没有前驱(即入度为零) 的顶点并输出。
    2. 从图中删除该顶点和所有以它为起点的有向边。
    3. 重复1和2直到当前的DAG图为空或当前图不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。
  • 通常,一个DAG图可以有一个或多个拓扑序列。

[ 1 ] ^{[1]} [1]:拓扑排序之所以只能针对于DAG图,就是因为它有每次取出入度为0的顶点的操作,如果有环,则环中的顶点不存在入度为0的点,无法进行拓扑排序。

tips2: \mathfrak\color{CornflowerBlue}\colorbox{Lavender}{tips2:} tips2:

关于拓扑排序的应用

拓扑排序一般很少有单独针对该知识点的题,但是在关键路径和平常的其他例题的辅助操作中却发挥着重要作用。所以掌握好拓扑排序是很重要的事情。

tips3: \mathfrak\color{CornflowerBlue}\colorbox{Lavender}{tips3:} tips3:

本代码按字典序输出的部分:

int j=1; //从第一个点开始查找
while(j<=n&&bein[j])
	j++; //统计入度为零的节点
//由于-1的bool值也视作真,所以可以标记为-1
if(j>n) return 0; //如果统计的节点超出了范围n,说明这个图有环
sum[++top]=j; //拓扑序列答案数组统计新答案
//本代码由邻接矩阵实现,按字典序输出,复杂度O(n^2)

#include <iostream>
#include <cstdio>

#define maxn 205
using namespace std;

int bein[maxn]; //bein[i]表示节点i的入度
int a[maxn][maxn]; //邻接矩阵存图
int sum[maxn],top; //拓扑序列答案数组
int n,m;

int TS()
{
	for(int i=1;i<=n;i++)
	{
		int j=1; //从第一个点开始查找
		while(j<=n&&bein[j])
			j++; //统计入度为零的节点
        //由于-1的bool值也视作真,所以可以标记为-1
		if(j>n) return 0; //如果统计的节点超出了范围n,说明这个图有环
		sum[++top]=j; //拓扑序列答案数组统计新答案
		bein[j]=-1; //标记此点已经遍历
		for(int k=1;k<=n;k++)
			if(a[j][k]) //如果j和k之间有边相连
				bein[k]--; //和j相关联的节点删除与j相连的边,即入度--
	}
	return 1; //如果遍历过程中没有返回过假值,则有解,返回真值
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		a[x][y]=1; //邻接矩阵储存单向边
		bein[y]++; //输入是从x到y的连线,所以是y的入度增加
	}
	if(TS()) //如果有解
		for(int i=1;i<=n;i++)
			cout<<sum[i]<<" "; //则输出节点的答案数组
	else
		cout<<"no solution"<<endl; //无解输出"no solution"
	return 0;
}

最小生成树

  • 最小生成树:在一张带权的无向连通图中,各边权和为最小的一颗生成树即为最小生成树。

    简单讲:找出连接所有点最低成本路线

  • 最小边原则 [ 2 ] ^{[2]} [2]:图中权值最小的边(如果唯一的话)一定在MST上。

  • 唯一性 [ 3 ] ^{[3]} [3]:一颗最小生成树上,如果各边的权都不相同,则最小生成树是唯一的。

[ 2 ] ^{[2]} [2]

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值