数据结构之图(最小生成树+最短路径)

news2024/11/26 6:19:24

基本概念

连通:若a->b存在路径,即为连通

连通图:该图中任意两点均连通,即为连通图

连通分量:下图为无向图,但存在三个连通分量

 强连通图:双向的连通图

强连通分量:有向图中的双向连通

图的存储结构

 邻接矩阵:顺序存储,二维数组耗费大量空间

原理:有路径flag=1,flag=0;

 

 

①无向图中为对称矩阵

②有向图中A [ i ] [ j ],i->j 或 j->i

邻接表:链式存储+顺序存储

 

 

图的遍历 

DFS 


1.变量设置:

map【】【】地图数组

book【】【】标记数组

dx【】,dy【】方向数组

2.终止条件

3.核心:

标记

递归dfs

回溯(取消标记)

#include<stdio.h>
int a[110][110];      //地图,0为通路,1为障碍物
int book[110][110];     //标记数组
int minn=999999,step;
int hx,hy;        //终点 
int min(int a,int b)
{
	return a<b?a:b;
}
void dfs(int x,int y,int step)
{
	//方向数组
	int dx[4]= {1,-1,0,0};
	int dy[4]= {0,0,1,-1};
	int tx,ty; 

	//终止条件
	if(hx==x&&y==hy)
	{
		minn=min(minn,step);
		return ;         //回溯 
	}

	for(int i=1; i<=4; i++)
	{
		int tx=x+dx[i];
		int ty=y+dy[i];

		if((a[tx][ty]==0)&&(book[tx][ty]==0))
		{
			book[tx][ty]=1;     //已走标记
			dfs(tx,ty,step+1);
			book[tx][ty]=0;     //取消标记
		}
	}
    return ; 
}
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		scanf("%d",&a[i][j]);
	}
	dfs(sx,sy);       //起点
	printf("%d",step); 
 } 

BFS 


1.结构体,x,y,step

2.首先起点入队,队首向四周扩展并将点(队尾)入队,直到不能扩展则队首出队,此时队尾变为队首,重复上述操作

#include<bits/stdc++.h>
using namespace std;
int a[100][100],v[100][100];
struct point
{
	int x;
	int y;
	int step;
};
queue<point> r;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int main()
{
	//输入
	int n , m ,startx,starty,p,q;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	
	scanf("%d%d%d%d",&startx,&starty,&p,&q);
	
	//BFS
	point start;
	start.x=startx; 
	start.y=starty; 
	start.step=0;
	r.push(start);//将起点入队 
	v[startx][starty]=1;
	int flag=0;
	while(!r.empty())
	{
		int x=r.front().x,y=r.front().y;
		if(x==p&&y==q)
		{
			flag=1;
			printf("%d",r.front().step);
			break;
		}
		for(int k=0;k<=3;k++)
		{
			int tx,ty;
			tx=x+dx[k];
			ty=y+dy[k];
			if(a[tx][ty]==1&&v[tx][ty]==0)
			{
				//入队 
				point temp;
				temp.x=tx;
				temp.y=ty;
				temp.step=r.front().step+1;
				r.push(temp);
				v[tx][ty]=1; 
			}
		}
		r.pop();//队首出队 
	 }
	 if(flag==0)
	 	printf("no answer!");
	 return 0; 
}
/*
5 4
1 1 2 1
1 1 1 1 
1 1 2 1
1 2 1 1 
1 1 1 2
1 1 4 3
*/

最小生成树 

原理: 

生成树:一个连通图的生成树是一个极小的连通子图,n个结点n-1条边;

最小生成树:边的权值之和最小的生成树,即从a->b的最短

若多一条边,则会构成回路(双向),若少一条边,则会缺一条路径;

算法实现:

Prim算法(稠密图)


从某一个单独结点开始,每次找权值最小的边,并连接其后继结点,构成整个最小生成树(n点n-1边)

#include <stdio.h>
#include <string.h>
#define INF 0x3f3f3f3f                        //无穷大
 
int n, m,a[1001][1001], dis[100001], ans;
int book[100001];
 
int main()
{
    memset(dis, INF, sizeof(dis));           //初始化dis【】大值
    dis[1] = 0;                              //起点自己到自己距离为0
 
 
    scanf("%d %d", &n,&m);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            scanf("%d", &a[i][j]);          //二维数组存图,i->j
        }
    }
 
    for(int i = 1; i <= n; i++)
    {
        int t = 0;
 
        for(int j = 1; j <= n; j++)
        {
            if(!book[j] && dis[j] < dis[t])       //寻找未标记且权值最短边(类似kruskal找最小边)
            {
                t = j;                            //记录最短边的终点t
            }
        }
 
        book[t] = 1;                          //标记,代表已加入最小生成树
        for(int j = 1; j <= n; j++)
        {
            if(!book[j] && a[t][j] < dis[j])     //更新最短距离
            {
                dis[j] = a[t][j];
            }
        }
    }
 
    for(int i = 1; i <= n; i++)
    {
        ans +=dis[i];                 //把所有在最小生成树中的点的权值加起来
    }
    printf("%d", ans);
    return 0;
}
 
 

 Kruskal算法(稀疏图)


从最小的边开始找,并连接最小边的两个结点,直到整个图形成最小生成树(n点n-1边)

#include<stdio.h>
#include<stdlib.h> 
int n,m;
long long sum;
int fa[200005];
int cnt=0;
struct node
{
    int x;
    int y;
    int z;
} a[200005];
 
void init(int n)
{
    for(int i = 1; i <= n; i++)
    {
        fa[i] = i;
    }
}
 
int find(int x)
{
    if(x==fa[x])
        return x;
    else
        return find(fa[x]);
}
 
int cmp(const void*a,const void*b)
{
    struct node aa=*(struct node*)a;
    struct node bb=*(struct node*)b;
    return aa.z>bb.z?1:-1;          //升序
    //降序:return aa.z>bb.z?-1:1;
}
 
int main()
{
    int v,k=0;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            scanf("%d", &v);
            if(j > i)                    //无向存图
            {
                k++;
                a[k].x = i;
                a[k].y = j;
                a[k].z = v;
            }
        }
    }
 
    qsort(a + 1,  a + k + 1, sizeof(a[1]),cmp);//排序函数
 
    for(int i = 1; i <= m; i++)
    {
        int x=find(a[i].x);
        int y=find(a[i].y);
        if(x!=y)                            //合并
        {
            f[y]=x;
            sum+=a[i].z;                //权值相加
            cnt++;
        }
        if(cnt==n-1)                  //n个点,n-1条边,边用完跳出循环 
            break;
    }
    printf("lld\n",sum);
    return 0;
}
0

 

 最短路径


从a->b的权值最小的一条路径

多源Floyed 


原理:利用三重循环,实时更新最短路径;

1.含义:

a【i】【j】:i--j 直接距离

a【i】【k】+ a【k】【j】:i--j 间接距离(经过k中转站)

2.解释:

求 i--j 的最短路径则讨论 i--j,i--1站点--j,i-2站点--j,i--3站点--j... ...

依次枚举比大小,实时更新

单源Dijkstra 


  

int dijk(int from,int to) //单源点到目标点
{
	int dis[N];    //距离数组
	int book[N];   //标记数组
	int map[N][N];   //存储两点间距离
	int pos;         //每次最短路径的站点 
	//book[from]=1;    //标记起点

	//初始化
	memset(book,0,sizeof(book));
	for(int i=1; i<=n; i++)
	{
		dis[i]=map[from][i];         //最初单源点到目标点的直达的距离,无中转站
	}
	//每次找最小边,连接其两点
	for(int i=1; i<=n; i++)         //遍历1-n个站点
	{
		int min=INF;
		for(int j=1; j<=n; j++)
		{
			if(min>dis[j])          //每次找最小边的对应点pos
			{
				min=dis[j];
				pos=j;
			}
		}
		book[pos]=1;             //找到并标记该点pos

		for(int k=1; k<=n; k++) //列举从1-n的站点,到达pos点的最短路径 
		{
			if((dis[pos]>dis[k]+map[k][pos])&&!book[k])
			{
				dis[pos]=dis[k]+map[k][pos];
			}
		}

	}
	return dis[to]; //所有站点的dis【】已经标记,找需求to即可 
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/429345.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享一个免梯子智能的问答工具ChatGPT,刷题和学习的好帮手

使用了这个问答工具后,感觉前后端都要被替代了,太强了。 由于本人之前很想体验,但是一直难搞,最近发现了一个免梯子的,重要事情说一遍,免梯子!是我最近发现的最好用,最快的,且不要梯子的,用起来爽,界面也挺好看的,大家快玩儿玩儿。 试了一下写代码,写文案……真棒…

文心一言 VS chatgpt (9)-- 算法导论2.3 7题 3.1 1题

七、描述一个运行时间为O(nlgn)的算法&#xff0c;给定n个整数的集合S和另一个整数&#xff0c;该算法能确定 S中是否存在两个其和刚好为工的元素。 文心一言&#xff1a; 这里是一个运行时间为O(nlgn)的算法&#xff0c;可以用来确定集合 S 中是否存在两个元素&#xff0c;它…

FE_CSS 页面布局之定位

1 为什么需要定位 某个元素可以自由的在一个盒子内移动位置&#xff0c;并且压住其他盒子。 当我们滚动窗口的时候&#xff0c;盒子是固定屏幕某个位置的。 以上效果&#xff0c;标准流或浮动都无法快速实现&#xff0c;此时需要定位来实现。 浮动可以让多个块级盒子一行没有…

第四章 word2vec 的高速化

目录4.1 word2vec 的改进①4.1.1 Embedding 层4.1.2 Embedding 层的实现4.2 word2vec 的改进②4.2.1 中间层之后的计算问题4.2.2 从多分类到二分类4.2.3 sigmoid 函数和交叉熵误差4.2.4 多分类到二分类的实现4.2.5 负采样4.2.6 负采样的采样方法4.2.7 负采样的实现4.3 改进版 w…

组态王与FX5U之间如何快速实现无线通讯?

本方案是基于Modbus RTU协议下实现的1主多从自组网无线通信形式&#xff0c;主站为组态王&#xff0c;从站为两台三菱FX5U PLC。在工厂里&#xff0c;组态王和plc所处位置距离较为分散&#xff0c;重新铺设电缆线工期长&#xff0c;成本高&#xff0c;故采用日系PLC专用无线通讯…

【Halcon 笔记2】参数

一、图形参数 图形参数 Iconic, 包括 image, region, XLD 1.1 image 图像由一个或者多个通道组成&#xff0c;是大小相同的矩阵&#xff0c;包含各种像素类型的灰度值 在图像显示界面&#xff0c;按ctrl健&#xff0c;可以查看当前的像素值 灰度图 一个通道像素点存放在一个…

STM32开发(十四)STM32F103 数据手册 —— 通用定时器 PWN 详解

文章目录主要特点通用定时器内部框图功能描述计数器模式计数器时钟可选择时钟源PWM输入模式STM32F103内部通用定时器包括TIMx (TIM2、 TIM3、 TIM4和TIM5)定时器 主要特点 16位向上、向下、向上/向下自动装载计数器 16位可编程(可以实时修改)预分频器&#xff0c;计数器时钟频…

【MySQL学习】认识MySQL数据库

目录一、什么是数据库二、主流数据库三、MySQL数据库的基本使用3.1 MySQL的安装3.2 MySQL服务器管理3.3 连接MySQL服务器3.4 MySQL服务器&#xff0c;数据库与表之间的关系3.5 使用案例3.6 数据存储四、MySQL架构五、SQL分类六、存储引擎6.1 定义6.2 查看存储引擎6.3 存储引擎对…

检测图中的负循环 | (贝尔曼福特)

我们得到了一个有向图。我们需要计算图形是否有负循环。负循环是循环的总和变为负的循环。 在图形的各种应用中都可以找到负权重。例如,如果我们沿着这条路走,我们可能会得到一些好处,而不是为一条路付出代价。 例子:

基于html+css的图片展示13

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

震惊!竟然有人如此解释关键字中的static

&#x1f929;&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;&#xff1a;这里是C专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;基础知识一网打尽&#xff0c;希望可以帮到读者们哦。 &#x1f…

工作中使用即时通讯软件有什么好处?

以前&#xff0c;即时通讯被认定为是一个专供个人使用的通信工具&#xff0c;即时消息软件不仅用于简化通信和快速响应&#xff0c;而且还用于文件共享和信息更新&#xff0c;它可帮助公司中的员工进行沟通、满足需求并实现目标。在即时通讯的帮助下&#xff0c;员工无需离开办…

交互式shell脚本编程2

当你在终端环境下安装新的软件时&#xff0c;你可以经常看到信息对话框弹出&#xff0c;需要你的输入&#xff0c;比如&#xff1a;RHEL/CentOS自带的setup&#xff0c;对话框的类型有密码箱、检查表、菜单等等。他们可以引导你以一种直观的方式输入必要的信息&#xff0c;使用…

3d可视化精炼数字工厂互动大屏展示提高企业竞争力

随着各种新兴技术的不断崛起和进步&#xff0c;结合云计算、5G通信、物联网等技术突破数据孤岛&#xff0c;加速炼钢厂整个行业的转型升级已成为行业的大趋势。 传统的维修场景中&#xff0c;一线员工的双手难以得到解放&#xff0c;一线工作数据难以收集、保存、输出。一辆汽车…

leetcode刷题(4)

各位朋友们&#xff0c;大家好。这两天我将为大家分享我在学习栈的过程中遇到的题目&#xff0c;我们一起来看看。 文章目录逆波兰表达式求值题目要求用例输入提示做题思路代码实现c语言实现代码Java语言实现代码有效的括号Java代码实现逆波兰表达式求值 leetcode之逆波兰表达…

Python基于机器学习实现的股票价格预测、股票预测源码+数据集,机器学习大作业

Feature与预测目标的选取 选择的feature: 开盘价最高成交价最低成交价成交量 选择的预测目标: 收盘价 因为股票价格的影响因素太多&#xff0c;通过k线数据预测未来的价格变化基本不可行&#xff0c;只有当天之内的数据还有一定的关联&#xff0c;故feature与target都选择的…

Oracle daily maintenancy-high active sessions

文章目录1.About check_mk metric:ORA_ORCL_Active_Session2.Solution2.1get the total number of active concurrent sessions2.2 the possible reason for this:2.2.1.High connection for normal behavior that happens occasionally2.2.2.resource competition1.About chec…

CentOS7---部署LNMP数据存储到redis

一、部署LNMP及redis 1、部署LNMP&#xff0c;需要将 tengine-2.2.0.tar.gz 拷贝到虚拟机的 /root 目录下 步骤一&#xff1a;安装nginx 源码安装相关软件包 # pcre-devel做正则匹配&#xff0c;zlib-devel做数据压缩 [roottemplate ~]# yum -y install gcc pcre-devel zlib-de…

迅为RK3588核心板平台新增工业级方案

迅为基于瑞芯微RK3588平台&#xff0c;提供商业级、工业级和国产化核心板&#xff0c;工业级板卡温度可达-40度到85度&#xff0c;国产化板卡从内存&#xff0c;存储等每一个元器件全部采用国产物料。不同板卡&#xff0c;满足各个行业需求。 iTOP-3588核心板参数 CPU &#x…

汉诺塔问题--C语言实现

魔王的介绍&#xff1a;&#x1f636;‍&#x1f32b;️一名双非本科大一小白。魔王的目标&#xff1a;&#x1f92f;努力赶上周围卷王的脚步。魔王的主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王.&#x1f525;&#x1f525;&#x1f525; ❤️‍&#x1…