Día 16 de la Copa Blue Bridge (Edición Python) (Teoría de grafos)

1. Precipitación máxima

 El problema es encontrar la mediana de la mediana, y las ideas anteriores para resolver problemas son fáciles de entender.

import os
import sys

# 请在此输入您的代码
# 降雨量为 7 周能量的中位数。
#1-7
#8-14
#15-21
#22-28
#29-35
#36-42
#43-49
#22-49 =28
# 后面28天尽可能的相同,这样中位数才能大


# 22+49 23+48  24+47  34
# 25+46 26+45  27+44  35
# 28+43 29+42  30+41  36
# 31+40 32+39  33+38  37

print(34)

2. Comparación del algoritmo de la ruta más corta

3. Algoritmo de Floyd (muchos a muchos, se puede simplificar a uno a muchos o muchos a uno)

Programación Dinámica, Principios

 Proceso computacional, combinado con comprensión gráfica.

 Pasos de cálculo (expandiendo k de 1 a n)

 Ecuación de simplificación de desplazamiento de matriz (observe con cuidado, k solo se usa en la capa anterior, por lo que se puede simplificar, simplemente deséchelo)

def floyd():
    global dp
    for k in range(1,n+1):
        for i in range(1,n+1):
            for j in range(1,n+1):
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])
dp = [[99999999 for _ in range(N) for _ in range(N)]  #dp[i,j]表示i到j最短路径

FloydEjemplo 1

dos formas de escribir


import math
def floyd():
    global dp
    for k in range(1,2022):
        #for i 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])
dp = [[9999999999 for _ in range(2022)] for _ in range(2022)]  #dp[i,j]表示i到j最短路径

for i in range(1,2022):
    for j in range(1,2022):
        if abs(i-j)<=21:
            dp[i][j]=i//math.gcd(i,j)*j
floyd()
print(dp[1][2021])
from math import gcd
def lcm(x,y):
    return x//gcd(x,y)*y
dp = [9999999999]*2022      # 点i到1的最短路径
dp[1]=0  #到自身的距离为0
for i in range(1,2022):  # 1-2022
    for j in range(i+1,i+22):  #和i有边的点j
        if j>2021:
            break
        dp[j] = min(dp[j],dp[i]+lcm(i,j)) # 更新最短路

print(dp[2021])

4.Dijkstra

Implementación de algoritmos

Por ejemplo:

 

 ejemplo:

 

 

import heapq  #导入堆,默认是小顶堆
def dij(s):
    done = [0 for i in range(n+1)]  # A:已确定为最短路径的点
    hp=[]   # 创建一个空堆
    dis[s]=0 #到自身的距离
    heapq.heappush(hp,(0,s))   # B:A的点向外扩散的邻居点,在堆中根据距离排序(从小到大)
    while hp:
        u = heapq.heappop(hp)[1] # 弹出最小元素
        if done[u]:  #表示被处理过了,起到了一个去重,更新小值的作用 
            continue
        done[u]=1
        for i in range(len(G[u])): #遍历u的邻居,把u的邻居放入B
            v,w = G[u][i]   # 邻居v,边长w
            if done[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**50
dis = [INF]*(n+1)  # 存储距离
for i in range(m): # 读m条边,这里是单向边
    u,v,w = map(int,input().split())
    G[u].append((v,w))  # 存图,u的一个邻居是v,边长是w

dij(s)
for i in range(1,n+1):
    if dis[i]>=INF:print("-1",end=' ')
    else:
        print(dis[i],end=' ')

5. Complemento de conocimiento de montón 

 

 6. Árbol de expansión mínimo

 

 

 La construcción del árbol de expansión mínimo se realiza mediante la búsqueda de unión. Si hay n puntos, el árbol de expansión mínimo tiene n-1 aristas. Cuando el árbol generado tiene n-1 aristas, salta fuera de la construcción.

 

problema del mono inteligente

 

problema de ruta

 

import os
import sys

# 请在此输入您的代码
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+1,i+22):  # 注意边界
    if j >2021: break
    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

problema del reino del puente azul

import heapq  # 导入堆
def dij(s):
    done=[0 for i in range(n+1)]  # 记录是否处理过
    hp=[]  #堆
    dis[s]=0
    heapq.heappush(hp,(0,s))   #入堆,小顶堆
    while hp:
        u=heapq.heappop(hp)[1] #出堆元素结点
        if done[u]: #当前结点处理过
            continue
        done[u]=1
        for i in range(len(G[u])): #遍历当前结点的邻居
            v,w =G[u][i]
            if done[v]:continue
            dis[v]=min(dis[v],dis[u]+w)  # 更新当前结点邻居的最短路径
            heapq.heappush(hp,(dis[v],v))




n,m = map(int,input().split())#
s=1  # 从1开始访问
G=[[]for i in range(n+1)]   #邻接表存储
inf = 2**50
dis = [inf]*(n+1) #存储距离
for i in range(m):# 存边,这里是单向边
    u,v,w = map(int,input().split())
    G[u].append((v,w))  #记录结点u的邻居和边长

dij(s)
for i in range(1,n+1):
    if dis[i]==inf:
        print("-1",end=' ')
    else:
        print(dis[i],end=' ')

problema del parque del puente azul

import os
import sys

# 请在此输入您的代码
#floyd算法,多对多


def floyd():
  global dp
  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)
   

Viaje de negocios (implementado en el formulario matricial de Dijstra)

import sys
#from typing import List

n, m = map(int, input().split())

# 邻接矩阵
gra = [[float('inf')] * (n+1) for _ in range(n+1)]
dist = [float('inf')] * (n+1)
g = [0] + list(map(int, input().split()))
g[n] = 0
st = [False] * (n+1)  # 标志是否被处理过

#  矩阵形式存储实现Dijkstra
def dijkstra():
    dist[1] = 0   #到自身距离为0
    for _ in range(n - 1): # 循环n-1次,因为还剩下n-1个点
        t = -1  #防止出现索引出界问题
        for j in range(1, n + 1):  #找到没处理过得最小最小距离点
            if not st[j] 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])
        st[t] = True # 标记为处理过了
    return dist[n]

for _ in range(m):
    u, v, c = map(int, input().split())
    gra[u][v] = g[v] + c
    gra[v][u] = g[u] + c

print(dijkstra())

Comprender principalmente (Floyd ( muchos a muchos (almacenamiento de forma de matriz) ), Dijstra ( 1 a muchos (lista de adyacencia, matriz) ) dos algoritmos)

problema del árbol de expansión mínimo

 Familiarizado con el uso de conjuntos de verificación

 

import math
def set_find(x):
    if x==_set[x]:
        return _set[x]
    else:
        _set[x]=set_find(_set[x])
        return _set[x]
    
def set_merge(x,y):
    if set_find(x)!=set_find(y): #需要合并
        #_set[x]=set_find(y)  # 合根指向y的根,这里有问题,即可能只改了一个的指向,要改这个连通块的根结点的指向
        _set[set_find(x)]=set_find(y)


       
_set=[i for i in range(1023)]  # 并查集初始化

n1=int(input())  # 猴子个数
m=list(map(int,input().split()))  # 读入最大跳入距离
n2=int(input())  #树的个数
location =[0]  #方便从1开始
edge_list=[]  #存储树的坐标


for i in range(n2):  # 存储树的坐标
    location.append(list(map(int,input().split())))

# 转换为图,记录每一条边
for i in range(1,n2):
    for j in range(i+1,n2+1):
      w=math.sqrt((location[i][0]-location[j][0])**2+(location[i][1]-location[j][1])**2)
      edge_list.append((i,j,w))  #按照 ( i,j,w ) 形式存储每一条边

# 开始生成最小生成树
maxvalue=0  # 记录生成树的最长边
num=0  #判断已经处理了多少条边
edge_list.sort(key=lambda x:x[2])  # 按边长从小到大排序
for i in  edge_list:
    if set_find(i[0])!= set_find(i[1]):
        set_merge(i[0],i[1])
        maxvalue = max(maxvalue,i[2])
        num+=1  # 处理了一条边
        if num==n2-1: #构建好了n-1条边,完成
            break

ans =0
for i in m:
    if i>=maxvalue:
        ans+=1
print(ans)

Oferta oficial

import math

class Edge:
    x = 0
    y = 0
    w = 0.0
    def __init__(self, x, y, w):
        self.x = x
        self.y = y
        self.w = w

def find(x):
    if f[x]==x:
        return f[x]
    else:
        f[x] = find(f[x])
        return f[x]

def merge(x,y):
    xx = find(x)
    yy = find(y)
    if xx!=yy:
        f[yy] = xx

if __name__ == '__main__':
    m = int(input())
    a = list(map(int, input().split()))
    n = int(input())
    x = [0 for i in range(n + 2)]
    y = [0 for i in range(n + 2)]
    for i in range(n):
        b = list(map(int, input().split()))
        x[i + 1] = b[0]
        y[i + 1] = b[1]
    edge_list = []
    maxvalue = 0
    num = 0
    for i in range(1, n + 1):
        for j in range(i + 1, n + 1):
            w = math.sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]))
            edge =  Edge(i, j, w)
            edge_list.append(edge)

    edge_list.sort(key=lambda x: x.w)
    f = [i for i in range(n + 1)]
    for i in edge_list:
        if find(i.x)!=find(i.y):
            merge(i.x,i.y)
            maxvalue = max(maxvalue,i.w)
            num+=1
            if num==n-1:
                break
    ans = 0
    for i in range(m):
        if a[i]>=maxvalue:
            ans+=1
    print(ans)

Supongo que te gusta

Origin blog.csdn.net/weixin_52261094/article/details/129809700
Recomendado
Clasificación