图论的总结(知足)(板子)

本文详细介绍了图论的基础概念,如有向/无向图、完全图等,并涵盖了路径、环、子图、联通性、度量、拓扑排序、最短路径算法(Dijkstra、Spfa)、割点和桥检测(Tarjan)以及Kruskal算法。这些内容是针对IT技术中数据结构和算法的学习资料,为即将到来的考试做准备。

寒假集训,今天是第七天,图论有关部分。

基础图论

图G是一个有序二元组(V,E),其中V称为点集(Vertices Set),E称为边集(Edges set),E与V不相交。它们亦可写成V(G)和E(G)。其中,点集的元素被称为顶点(Vertex),边集的元素被称为边(edge)

一些定义

有向/无向图 :边具有/不具有方向

完全图:每一对不同顶点恰有一条边相连的无向图

路径:一些边和对应点的序列,使得前一条边的终止点等于下一条边的起始点。

简单路径:经过的点不重复的路径

环:一条首尾相连的路径

简单环:一条首尾相连的简单路径

自环:端点在同一点的边

重边:两条端点相同的边

一些概念

子图:点集V的一个子集V’和端点在V’内部的边集E’构成的图(V’,E’)

联通:两点间存在路径

联通图:任意两点都联通的图

顶点的度:点相连的边的个数

点的入度:有向图以该点为终点的边的个数

点的出度:有向图以该点为起点的边的个数

完全图:每一对不同顶点恰有一条边相连的图

一些板子

存储-链式前向星
//链式前向星 
void add(int x,int y,int z)
{
	to[cnt ++] = y;
	v[cnt] = z;
	nxt[cnt] = head[x];
	head[x] = cnt;
}
//输出所有从x出发的终点和边权
for(int i = head[x];i;i = nxt[i])
printf("%d %d",to[i],v[i]); 
图的遍历
//图的遍历:dfs/bfs
void dfs(int x)
{
	vis[x] = 1;
	printf("%d\n",x);
	for(int i = head[i];i;i = nxt[i])
	if(!vis[to[i]])
	dfs(to[i]);
}
---------------
void bfs(int x)
{
	z[top ++] = x;
	for(int i = 1;i <= top;i ++)
	{
		int noe = z[top ++];
		printf("%d\n",now);
		for(int j = head[now];j;j = nxt[j])
		if(!vis[to[j]])
		vis[to[j]] = 1,z[top ++] = to[j];
	}
}
欧拉路径
//欧拉路径
void dfs(int x)
{
	for(int i = head[x];i;i = nxt[i])
	if(!vis[i])
	vis[i] = 1,dfs(to[i]);
	cout << x;
}
拓扑排序
//拓扑排序
	for(int i = 1;i <= n;i ++)
	if(d[i] == 0)
	z[top ++] = i;
	for(int i = 1;i <= top;i ++)
	{
		for(int j = head[z[i]];j;j = nxt[j])
		{
			d[to[j]] --;
			if(d[to[j]] == 0)
			z[top ++] = to[j];
		}
	}
多源最短路
//多源最短路 
	for(int k = 1;k <= n;k ++)
	{
		for(int i = 1;i <= n;i ++)
		{
			for(int j = 1;j <= n;j ++)
				f[i][j] = min(f[i][j],f[i][k] + f[k][j]);
		}
	}
Dijkstra单源
//Dijkstra
struct node
{
	int id,dis;
	friend bool operator < (node x,node y)
	{
		return x.dis > y.dis;
	}
};
priority_queue <node> q;

memset(dis,0x3f,sizeof(dis))
	dis[1] = 0;
	q.push({0,0});
	while(!q.empty())
	{
		now = (q.top()).id;
		q.pop();
		if(vis[now])
		continue;
		vis[now] = 1;
		for(int i = head[now];i;i = nxt[i])
		{
			if(dis[to[i]] > dis[now] + w[i])
			{
				dis[to[i]] = dis[now] + w[i];
				q.push({to[i],dis[to[i]]});
			}
		}
	}
Spfa单源
//Spfa(他死了)
void spfa()
{
	memset(dis,0x3f,sizeof(dis));
	dis[s] = 0;
	z[top = 1] = s;
	for(int i = 1;i <= top;i ++)
	{
		int now = z[j];
		vis[now] = 0;
		for(int i = head[now];i;i = nxt[i])
		{
			if(dis[to[i]] > dis[now] + w[i])
			{
				dis[to[i]] = dis[now] + w[i];
				if(!vis[to[i]])
				vis[to[i]] = 1;
				z[top ++] = to[i];
			}
		}
	}
}
Tarjan单源
//求割点
void dfs(int u,int fa)
{
	low[u] = dfn[u] = dfs_clock ++;
	int c = 0;
	for(int i = head[u];i;i = nxt[i])
	{
		int v = to[i];
		if(!dfn[v])
		{
			dfs(v,u);
			c ++;
			low[u] = min(low[u],low[v]);
			if(low[v] >= dfn[u])
			cut[u] = 1;
		}
		else
		if(dfn[v] < dfn[u] && v != fa)
		low[u] = min(low[u],dfn[v]);
	}
	if(c == 1 && fa == 0)
	cut[u] = 0;
}
//求桥 
void tarjan(int u,int fa)
{
	dfn[u] = low[u] = dfs_clock ++;
	for(int i = head[u];i;i = nxt[i])
	{
		int v = l[i].t;
		if(fa == v)
		continue;
		if(!dfn[v])
		{
			tarjan(v,u);
			low[u] = min(low[u],low[v]);
			if(low[v] > dfn[u])
			bcnt ++,bri[l[i].id] = 1;
		}
		else
		if(dfn[v] < dfn[u])
		{
			low = min(low[u],dfn[v]);
		}
	}
}
Kruskal
//Kruskal
	for(int i = 1;i <= m && cnt < n - 1;i ++)
	{
		int x = e[i].from,y = e[i].to,z = e[i].w;
		int u = find(x),v = find(y);
		if(u == v)
		continue;
		fa[u] = v;
		cnt ++;
		add(x,y,z);
		add(x,y,z);
	}

总结

以上板子来自lyn学长A2391833679 的用心整理,表示衷心感谢!本人依照自己的码风稍加修改。

马上就要HL了,希望这佛脚不会让我爆零(doge

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值