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

news/2025/2/12 18:51:59/

基本概念

连通:若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);//BFSpoint 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;                              //起点自己到自己距离为0scanf("%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;elsereturn 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;             //找到并标记该点posfor(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.ppmy.cn/news/44369.html

相关文章

linux线程调度策略

系统中既有分时调度&#xff0c;又有时间片轮转调度和先进先出调度 学习这个主要为了在linux多线程中&#xff0c;解决几条指令间延时在1-2ms内&#xff1b; 1.比如之前处理过&#xff1a;给一个板子发送一个can指令&#xff0c;接着需要给另外一个模块发送移动指令&#xff0c…

APIs --- DOM事件进阶

1. 事件流 事件流指的是事件完整执行过程中的流动路径 任意事件被触发时总会经历两个阶段&#xff1a;【捕获阶段】和【冒泡阶段】 事件捕获 概念&#xff1a;从DOM的根元素开始去执行对应的事件&#xff08;从外到里&#xff09; 捕获阶段是【从父到子】的传导过程 代码&…

02.容器实现BeanFactory和ApplicationContext实现

容器实现BeanFactory和ApplicationContext实现 BeanFactory实现的特点ApplicationContext的常见实现和用法内嵌容器、注册DispatcherServlet 1. BeanFactory的实现 BeanFactory不会主动添加BeanFactoryPostProcessor&#xff1b;BeanFactory后处理器主要功能&#xff1a;补充了…

DAY 37 shell免交互

Here Document 概述 常用的交互程序&#xff1a;read&#xff0c;ftp&#xff0c;passwd&#xff0c;su&#xff0c;sudo cat也可配合免交互的方式重定向输出到文件 Here Document 的作用 使用I/O重定向的方式将命令列表提供给交互式程序标准输入的一种替代品 格式 命令 &…

Samba共享

关闭selinux跟防火墙 setenforce 0 systemctl stop firewalld 安装samba以及客户端 yum install samba samba-client -y 创建共享目录 mkdir -p /data/share1 mkdir -p /data/public 添加samba用户并配置权限 useradd zsuser smbpasswd -a zsuser 修改配置文件并重启服…

runtime中加入多线程和应用开发

1. 单线程的runtime nvinfer1::runtime: 创建推理运行时runtime runtime->(load(engine)): 反序列化mengine mengine->context: 创建执行上下文context buffer(mengine): 创建输入输出的缓冲区, 确定cap输入文件是视频文件还是RTSP流&#xff0c; 并且获取数据, 是否推…

商医通项目总结

一、项目概述 简介 尚医通即为网上预约挂号系统&#xff0c;网上预约挂号是近年开展的一项便民就医服务&#xff0c;旨在缓解看病难、挂号难的就医难题。网上预约挂号全面提供的预约挂号业务从根本上解决了这一就医难题。随时随地轻松挂号&#xff0c;不用排长队 微服务项目…

【Python_Scrapy学习笔记(十一)】基于Scrapy框架的下载器中间件添加Cookie参数

基于Scrapy框架的下载器中间件添加Cookie参数 前言 本文中介绍 如何基于 Scrapy 框架的下载器中间件添加 Cookie 参数。 正文 1、添加中间件的流程 在 middlewares.py 中新建 Cookie参数 中间件类在 settings.py 中添加此下载器中间件&#xff0c;设置优先级并开启 2、基…