图论专题(各类算法和蓝桥杯真题例题)

news2024/9/23 9:30:18

1.图论入门

1.1存边方式

1.1.1 数组存边

 1.1.2 临接矩阵存边

 1.1.3 临接表存边

 1.2 图的遍历和连通性

通过DFSBFS遍历每一个图

对于非连通图,循环对每一个点dfs操作

也可以通过并查集来判断连通性

1.2.1全球变暖例题

import sys
sys.setrecursionlimit(60000)  # 设置最大递归深度,默认递归深度有点小,不设置递归会出问题
 
def dfs(x,y):
  d=[(-1,0),(0,1),(1,0),(0,-1)]  # 左 上 右 下
  global flag
  vis[x][y] =1
  if mp[x][y+1]=='#' and mp[x][y-1] =='#' and mp[x+1][y]=='#' and mp[x-1][y]=='#':
    # 说明点(x,y)四周都是陆地
    flag = 1  # 高地标记,不会被淹没
  for i in range(4):
    nx=x+d[i][0]
    ny=y+d[i][1]
    if vis[nx][ny] ==0 and mp[nx][ny] =='#':
      # 如果当前没有遍历点(nx,ny)同时地图上面该点不是陆地
      dfs(nx,ny)
 
n=int(input())
mp = []   # 记录地图
for i in range(n):
  mp.append(list(input()))
vis =[]   # 判断是否走过
for i in range(n):
  vis.append([0]*n)
 
ans =0
for i in range(n):  # 遍历每一点
  for j in range(n):
    if vis[i][j] ==0 and mp[i][j] =='#':  # 相当于找连通分量
      flag = 0
      dfs(i,j)
      if flag==0:
        ans+=1
 
print(ans)
    

1.3 欧拉路和欧拉回路

 哈密顿回路:图中每个点通过且只通过一次

1.3.1欧拉路和欧拉回路判定

        无向图

        如果图中的点全都是偶点,则存在欧拉回路;任意一点都可以作为起点和终点。

        如果只有2个奇点,则存在欧拉路,其中一个奇点是起点,另一个是终点。不可能出现有奇数个奇点的无向图。

        有向图

        把一个点上的出度记为1,入度记为 -1,这个点上所有出度和入度相加,就是它的度数。
        一个有向图存在欧拉回路,当且仅当该图所有点的度数为零。
        如果只有一个度数为1的点,一个度数为-1的点,其它所有点的度数为0,那么存在欧拉路径,其中度数为1的是起点,度数为–1的是终点。

1.3.2 欧拉路劲例题

## 不全,没看懂
import sys
import collections
import itertools
import heapq
sys.setrecursionlimit(300000)

def dfs(u):
    i=d[u]   # 从点u的第一条边i=0开始
    while(i<len(G[u])):
        d[u]=i+1  # 后面继续走u的下一条边
        dfs(G[u][i]) # 继续走这条边的邻居点
        i=dp[u]   # 第i条边走过了,不再重复走
    rec.append(u)

M=100100
n,m = map(int,input().split())  # n个点,m条边
du=[[0 for _ in range(2)] for _ in range(M)]  # 记录入度,出度
G=[[] for _ in range(n+1)]  # 临接表存图
d=[0 for _ in range(M)]  # d[u]=i : 当前走u的第i个边
rec=[]   #记录欧拉路
    

for i in range(m):
    u,v =map(int,input().split())
    G[u].append(v)
    du[u][1]+=1   #出度
    du[v][0]+=1   #入度
for i in range(1,n+1):
    G[i].sort()   # 对邻居点排序,字典序
    S=1

2.Floyd算法

2.1 Floyd介绍

 算法对比

 2.2算法模板

import sys
import collections
import itertools
import heapq
sys.setrecursionlimit(300000)

def floyd():
    for k in range(1,n+1):
        for i in range(1,n+1):
            for j in range(1,n+1):
                if dp[i][k]+dp[k][j] <dp[i][j]:
                    dp[i][j]=dp[i][k]+dp[k][j] 

 2.3 算法总结

 2.4 算法例题

2.4.1 蓝桥公园

import sys
import collections
import itertools
import heapq
sys.setrecursionlimit(300000)



def floyd():
  for i in range(1,n+1):
    for j in range(1,n+1):
      for k in range(1,n+1):
        dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])
 
n,m,q = map(int,input().split())
inf=2**120  #自定义无穷大
dp=[[inf]*(n+1) for i in range(n+1)]  # 初始为无穷大
choice=[]
for i in range(m):
  u,v,w=map(int,input().split())   # 无向图,临接矩阵存边
  dp[u][v]=w
  dp[v][u]=w 
for i in range(q):   # 读 起点和终点
  s,d = map(int,input().split()) 
  choice.append((s,d))
floyd()
for s,d in choice:
  if dp[s][d]!=inf:
    print(dp[s][d])
    continue
  print(-1)
   

2.4.2 路径

 标准的floyd算法

import sys
import collections
import itertools
import heapq
import math
sys.setrecursionlimit(300000)


# 标准的floyd


def lcm(x,y):   # 求最下公倍数
    return x//math.gcd(x,y)*y

def floyd():
    for k in range(1,2022):
        for i in range(1,2022):
            for j in range(1,2022):
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])

        
dp=[[int(0x3f3f3f3f3f3f3f) for _ in range(2022)] for _ in range(2022)]
for i in range(1,2022):
    for j in range(1,2022):
        if abs(i-j)<=21:  # 题意中的如果两个结点的差的绝对值不大于21
            dp[i][j]=lcm(i,j)

print(dp[1][2021]

 简化版Floyd算法

import sys
import collections
import itertools
import heapq
sys.setrecursionlimit(300000)


import math
def lcm(i,j):
  return i//math.gcd(i,j)*j
 
dp=[[2**50]*2022 for i in range(2022)]
# 创建图
for i in range(1,2022):
  for j in range(i,2022):  
    if abs(i-j)<=21:
      dp[i][j]=lcm(i,j)
 
# 找最短路径
for k in range(1,2022):
  for i in range(1,2):
    for j in range(1,2022):
      dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])
print(dp[1][2021])  # 1026837
 

Bellman-Ford算法

import sys
import collections
import itertools
import heapq
import math
sys.setrecursionlimit(300000)


# Bellman_Ford算法


def lcm(x,y):   # 求最下公倍数
    return x//math.gcd(x,y)*y
        
dp=[int(0x3f3f3f3f3f3f3f) for _ in range(2022)]
for i in range(1,2022):
    for j in range(i+1,i+22): # 题意中的如果两个结点的差的绝对值不大于21
        if j>2021: break
            dp[j]=min(dp[j],dp[i]+lcm(i,j))  # 更新最短路

print(dp[2021])

3.Dijstra算法

3.1 算法简介

 

 3.2算法举例

 3.3 例题模板

3.3.1 蓝桥王国

import sys
import collections
import itertools
import heapq   # 默认小顶堆
import math
sys.setrecursionlimit(300000)


def dij(s):
    vis=[0 for i in range(n+1)]  # 标志是否访问过
    hp=[]  # 堆
    dis[s]=0  # 自身到自身的距离为0
    heapq.heappush(hp,(0,s))  # 列表堆化同时入堆
    while hp:
        u=heapq.heappop(hp)[1]  # 出堆,出的是结点
        if vis[u]: # 判断是否处理过
            continue
        vis[u]=1
        for i in G[u]:
            v,w=i[0],i[1]
            if vis[v]:
                continue
            if dis[v]>dis[u]+w:
                dis[v]=dis[u]+w
                heapq.heappush(hp,(dis[v],v))
    

n,m=map(int,input().split())
s=1
G=[[]for i in range(n+1)]  # 临接表存图
inf=2**64
dis=[inf]*(n+1)   # 从1到其他点的距离
for i in range(m):  # 邻接表存m条边
    u,v,w=map(int,input().split())
    G[u].append((v,w))
dij(s)   # 以s为起点到其他点的最短路径
for i in range(1,n+1):
    if dis[i]>=inf :
        print("-1",end=' ')
    else:
        print(dis[i],end=" ")
    

3.3.2 矩阵矩阵形式的Dijstra模板

 

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)
 
 
 
def dij():
   dist[1]=0  #很重要
   for _ in range(n-1): # 还有n-1个点没有遍历
      t=-1
      for j in range(1,n+1):
         if st[j]==0 and (t==-1 or dist[t]>dist[j]):  #找到没处理过得最小距离点
            t=j
      for j in range(1,n+1):
         dist[j]=min(dist[j],dist[t]+gra[t][j])  # t-j的距离,找最小值
      st[t]=1  # 标记处理过
   return dist[n]
      
n,m=map(int,input().split())
 #下标全部转为从1开始
stay=[0]+list(map(int,input().split()))
stay[n]=0   
gra = [[float('inf')] * (n+1) for _ in range(n+1)]
dist = [float('inf')] * (n+1)
st=[0]*(n+1)  # 标志是否处理
 
 
for i in range(m):
   u,v,w=map(int,input().split()) #这里重构图
   gra[u][v]=stay[v]+w
   gra[v][u]=stay[u]+w
 
 
print(dij())
   

4.Bellman-Ford算法

4.1 算法简介

单源最短路径问题:给定一个起点s,求它到图中所有n个结点的最短路径。

 4.2 算法模板和例题

4.2.1 出差问题

 Bellman——Ford实现

import sys
import collections
import itertools
import heapq   # 默认小顶堆
import math
sys.setrecursionlimit(300000)

n,m = map(int,input().split())
t=[0]+list(map(int,input().split()))  # 从t=1开始
e=[]  # 数组存边
for i in range(1,m+1):
    a,b,c = map(int,input().split())
    e.append([a,b,c])
    e.append([b,a,c])    # 双向边

dist=[2**64]*(n+1)  # 存储到终点的距离
dist[1]=0
for k in range(1,n+1):  # 最大循环n次,即n个点
    for a,b,c in e:  # 检查每条边
        res=t[b]  # b的隔离时间
        if b==n:
            res=0
        dist[b]=min(dist[b],dist[a]+c+res)   # 问邻居是否能到达起点
print(dist[n])

 Dijstra实现

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)
 
 
 
def dij():
   dist[1]=0  #很重要
   for _ in range(n-1): # 还有n-1个点没有遍历
      t=-1
      for j in range(1,n+1):
         if st[j]==0 and (t==-1 or dist[t]>dist[j]):  #找到没处理过得最小距离点
            t=j
      for j in range(1,n+1):
         dist[j]=min(dist[j],dist[t]+gra[t][j])  # t-j的距离,找最小值
      st[t]=1  # 标记处理过
   return dist[n]
      
n,m=map(int,input().split())
 #下标全部转为从1开始
stay=[0]+list(map(int,input().split()))
stay[n]=0   
gra = [[float('inf')] * (n+1) for _ in range(n+1)]
dist = [float('inf')] * (n+1)
st=[0]*(n+1)  # 标志是否处理
 
 
for i in range(m):
   u,v,w=map(int,input().split()) #这里重构图
   gra[u][v]=stay[v]+w
   gra[v][u]=stay[u]+w
 
 
print(dij())
   

5.SPFA算法

5.1 算法简介

改进的Bellman-Ford算法

 5.2 算法步骤

5.3 算法例题和模板

5.3.1 随机数据下的最短路问题

import sys
import collections
import itertools
import heapq   # 默认小顶堆
import math
sys.setrecursionlimit(300000)


def spfa(s):
    dis[s]=0
    hp=[]
    heapq.heappush(hp,s)
    inq=[0]*(n+1)   # 判断是否在队列中
    inq[s]=1
    while(hp):
        u=heapq.heappop(hp)
        inq[u]=0
        ''' 下面两句认为没用,因为队列中的u都是因为上一个结点的邻居更新后
            放进来的,删了之后一样AC '''
        if dis[u]==inf:   #到起点的距离为无穷大,没有必要更新邻居
            continue
        for v,w in e[u]:    # 遍历u的邻接表
            if dis[v]>dis[u]+w:
                dis[v]=dis[u]+w
                if(inq[v]==0):  # 状态有更新,v的邻居可以通过他得到更近路径
                    heapq.heappush(hp,v)
                    inq[v]=1
n,m,s = map(int,input().split())
e=[[] for i in range(n+1)]  # 临接表存边
inf=2**64
dis=[inf]*(n+1)
for i in range(m):  # 读边
    u,v,w = map(int,input().split())
    e[u].append((v,w))   # 邻接表存边,有向图
spfa(s)
for i in range(1,n+1):
    if dis[i]>=inf:
        print('-1',end=' ')
    else:
        print(dis[i],end=' ')

 5.4 Dijstra和SPFA对比

6.最小生成树算法

6.1 Prim算法

6.1.1 修建公路(例题模板)

import sys
import collections
import itertools
import heapq   # 默认小顶堆
import math
sys.setrecursionlimit(300000)


def prim():
    ans,cnt=0,0   # cnt 是加入MST的点的数量
    q=[]
    vis=[0 for i in range(n+1)]   # 1 表示点在MST中
    heapq.heappush(q,(0,1))
    while q and cnt<n:
        w,u = heapq.heappop(q)   # 出距离集合最近的点
        if  vis[u] !=1:  # 不再MST中
            vis[u]=1
            ans+=w
            cnt+=1
            for v,w in e[u]:   # 遍历点u的邻居,边长为w
                heapq.heappush(q,[w,v])  # 加入MST的点的数量不等于n,说明原图不连通
    if cnt!=n:   # 加入MST的点的数量不等于n,说明原图不连通
        print('-1')
    else:
        print(ans)

        
n,m = map(int,input().split())
e=[[] for i in range(n+1)]
for i in range(m):
    u,v,w  =map(int,ipnut().split())
    e[u].append((v,w))  # u的邻居是v,边长w
    e[v].append((u,w))  # 双向边

prim()

6.2 Krusal算法

通过并查集实现

 6.2.1 例题模板(修建公路)

import sys
import collections
import itertools
import heapq   # 默认小顶堆
import math
sys.setrecursionlimit(300000)


def find(x):
    if s[x] ==x:
        return x
    s[x]=find(s[x])  # 路径压缩
    return s[x]

def merge(x,y):
     s[find(y)]=find(x)
def kruskal():
    cnt=0
    ans=0
    e.sort(key=lambda x: x[2])  # 将边从小到大排序
    for i in range(n+1):   # 并查集初始化
       s.append(i)
    for i in range(m):  # 遍历所有边
        x,y=e[i][0],e[i][1]
        e1,e2 =find(x),find(y)
        if e1==e2:  # 属于同一个集,要这条边的话产生圈
            continue
        else:
            ans+=e[i][2]
            merge(x,y)
            cnt+=1
        if cnt==n-1:
            break
    if cnt!=n-1:   # 边的数量不等于n-1,说明有点不再MST上面
        print(-1)
    else:
        print(ans)
    return
e=[]  # 数组存边
s=[]  # 并查集
n,m=map(int,input().split())
for i in range(m): # 存m条边
    u,v,w = map(int,input().split())
    e.append((u,v,w))   # 存边
kruskal()

6.3 两种算法对比

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

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

相关文章

【目标检测】Haar-like特征检测简介

文章目录 一、背景模板匹配&#xff08;template matching&#xff09;关键点检测角点检测 二、harris特征提取原理Harris Detector 的具体流程&#xff1a;harris特征的可复用性旋转尺度 scale亮度 illuminationview point 三、Viola Jones检测原理Harr-like特征提取积分图训练…

QT教程demo之串口助手代码设计实现

关注WeChat Official Account 南山府嵌入式获取更多精彩 我创建了一个群关注V号后加入。因为这里不允许添加二维码 代码&#xff1a;QT_Pr 1-QT开发串口助手需要的基本文件 在QT6开发串口助手时&#xff0c;通常需要以下头文件&#xff1a; #include <QSerialPort> #i…

TCP协议策略

TCP可靠性 基于序号的确认应答(ACK)机制 TCP保证可靠性最核心的机制就是基于序号的确认应答机制。 TCP并不是百分之百可靠的&#xff0c;但是只要一条消息有应答&#xff0c;那么我们就可以确定该消息100%被对方收到了&#xff0c;这就是确认应答的意义。 可靠性不仅仅是保…

MOSS模型量化版部署过程

文章目录 项目背景配置环境与准备部署推理命令行部署报错1报错2&#xff1a; 网页版部署 项目背景 2023年4月21日&#xff0c;复旦大学自然语言处理实验室正式开放MOSS模型&#xff0c;是国内首个插件增强的开源对话大语言模型。MOSS 相关代码、数据、模型参数已在 GitHub 和 …

【键入网址到网页显示】

HTTP 对 URL 进行解析之后&#xff0c;浏览器确定了 Web 服务器和文件名&#xff0c;接下来就是根据这些信息来生成 HTTP 请求消息了。 http://www.server.com/dir1/file1.html http:访问数据的协议 www.server.com:服务器 dir1:目录名 file1.html:文件名生产 HTTP 请求信息…

SpringCloud-10_Alibaba Nacos

SpringCloud系列 SpringCloud-9、SleuthZipkin SpringCloud-8、Gateway网关服务 SpringCloud-7_OpenFeign服务调用 SpringCloud-6_Ribbon负载均衡 SpringCloud-5_模块集群化 文章目录 SpringCloud系列Nacos基础Nacos是什么&#xff1f;Nacos下载&运行 创建Nacos服务提供者…

JavaScript:哈希表

文章目录 哈希表242. 有效的字母异位词思路补充&#xff1a;JavaScript String charCodeAt() 方法代码详细分析 349. 两个数组的交集代码分析补充&#xff1a;JavaScript Set 对象思考一下哈希是什么&#xff1f;什么时候使用&#xff1f;补充&#xff1a;js 数组 map() 基本用…

github使用workflow工作流git push后自动打包部署github pages

workflows介绍 根目录新建.github/workflows/docs.yml .github/workflows/ 目录是用于存放 GitHub Actions 工作流程文件的目录&#xff0c;该目录的文件名必须以 .yml 或 .yaml 为后缀名&#xff0c;否则 GitHub 将无法识别该文件为工作流程文件。这些工作流程文件可用于自动…

速锐得基于能源油气生产智能监控的物联网应用

自2016年速锐得基于商用车国六环保排放监控管理开发以来&#xff0c;我们同时也接触了很多涉及商用车领域的深入项目&#xff0c;包括了大庆油田、山东能源、兖矿集团、陕北矿业等多家能源巨头在数字化、科技、无线远程控制、监控管理、生产效能等方面的智能化方向的趋势。 就目…

MySQL 字段为 NULL 的5大坑,大部分人踩过

数据库字段允许空值(null)的问题&#xff0c;小伙伴你遇到过吗&#xff1f; 在验证问题之前&#xff0c;我们先建一张测试表及测试数据。 构建的测试数据&#xff0c;如下图所示&#xff1a; 有了上面的表及数据之后&#xff0c;我们就来看当列中存在 NULL 值时&#xff0c;究…

基于RGB-D的6D目标检测算法

基于RGB-D的6D目标检测算法 本文参考了ITAIC的文章 A Review of 6D Object Pose Estimation 概览 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eQX8ke6j-1683188966051)(https://mezereon-upic.oss-cn-shanghai.aliyuncs.com/uPic/image-20230420…

如何理解信息化、数字化和智能化的概念?一文给你解惑!

如何理解信息化、数字化和智能化的概念&#xff1f; 前两年流行“信息化”&#xff0c;网上铺天盖地都是关于“信息化”的文章&#xff0c;这两年开始流行起“数字化”&#xff0c;于是铺天盖地都是“数字化”的文章&#xff0c;最近又开始大谈“智能化”...... 但点开那些文…

常见的5种项目管理问题类型

项目管理的5大影响素&#xff1a;时间、范围、成本、风险、质量。项目经理需要对这些因素进行均衡考量&#xff0c;并根据需要略有侧重&#xff0c;进行整体把握&#xff0c;即我们常说的均衡型管理风格。而忽略任何一因素&#xff0c;都会对项目产生极大影响。 常见的项目管理…

医院导诊图怎么做?目前比较好用的医院导航地图是哪一款?

现在很多的大医院&#xff0c;不只是越建越高&#xff0c;面积也越来越大&#xff0c;同时医院内部按照门诊、住院、放射等不同功能划分的区域也是越来越多&#xff0c;走进这些“超级医院”就像走进了迷宫一样&#xff0c;如何促使病患走进医院后&#xff0c;能迅速找到要去的…

19C RAC主库 to RAC备库搭建adg报错ORA-16047(修改19C RAC DB_UNIQUE_NAME )

文章目录 前言一、问题描述二、修改DB_UNIQUE_NAME1.查看集群配置2.将hip40实例从集群中移除3.修改db_unique_name4.将hip40dg实例添加到集群资源中5.重新启动实例 三、19C RAC 密码文件替换 前言 主库环境是19C RAC备库环境也是19C RAC&#xff0c;主库到备库做adg&#xff0…

移动端动态开发能力的由来和流派

移动端动态化的由来 “动态化”并不是最近几年才产生的名词&#xff0c;而是从从互联网诞生的初期&#xff0c;这个词就已经出现了。大家所认知的早期互联网&#xff0c;其实就是各种各类的“动态网站”&#xff0c;内容数据和页面外观都不是固定的&#xff0c;都是随着服务器…

Bash脚本中的Sleep命令到底有何妙用?

在编写Bash脚本时&#xff0c;有时需要在程序执行过程中加入一些等待时间&#xff0c;例如等待某个操作完成或等待某个进程退出。此时可以使用sleep命令来实现。 sleep命令可以让脚本暂停执行一段时间&#xff0c;其基本语法为&#xff1a; sleep <seconds>其中&#xf…

细数【SD-WEBUI】的模型:谁是最适合的模型从哪里找到它们

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;基础模型&#xff08;Stable-Diffusion模型&#xff09;&#xff08;1.1&#xff09;ChilloutMix&#xff08;仿真&#xff09;&#xff08;1.2&#xff09;BasilMix&#xff08;仿真&#xff09;&#xff0…

如何使用 Linux Cron Job 优化WP-Cron以获得更好的性能

在本教程中&#xff0c;我将向您展示如何通过在 Linux 上用 Crontab 替换默认的 WP-Cron 触发机制来优化 WordPress 性能。 WordPress 使用 WP-Cron 来运行计划任务&#xff0c;许多用户已经在使用。 但它的工作方式并不理想。 在每次页面加载时&#xff0c;WP-Cron 检查计划…

在Centos7上安装和配置canal

1. 在 MySQL 数据库中创建 Canal 账户并为其授权 在安装 Canal 前&#xff0c;你需要在 MySQL 数据库中创建一个用于 Canal 连接的账户&#xff0c;并为该账户授予必要的权限。 以下是在 MySQL 数据库中创建 Canal 账户并为其授权的步骤&#xff1a; 登录 MySQL 使用以下命令…