Floyd模板题 P1704

本文深入讲解了Floyd算法在处理连通图上的应用,包括求解两点间最短路径、最大边最小路径及最小边最大路径的问题。通过具体实例演示了算法的实现过程,为读者提供了清晰的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

给出N个顶点,M条无向带权边的连通图,和Q个查询:请编程回答:
问1、两点之间的最短路径(边权和最小的路径);
问2、两点之间的所有路径中,需要经过的最小边的最大的路径(最大边最小);
问3、两点之间的所有路径中,需要经过的的最大边的最小的路径(最小边最大);


Input

第一行:N(N<=400),M(M<=10000),Q(Q<=100)查询数量。接下来M行,每行三个整数:x,y,t(1<=x,y<=N)


Output

包含Q行,对应输入数据中的查询。


Hint

N<=400M<=10000


Solution

Floyd模板题。可以处理负权图,时间复杂度是O(n^3)。比较慢但是简单啊。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 405
#define inf 0x3f3f3f3f
using namespace std;
int dist1[maxn][maxn],dist2[maxn][maxn],dist3[maxn][maxn],g[maxn][maxn];
int n,m,q,s,t,x,y,z;
void init(){
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j)g[i][j]=0;
            else g[i][j]=inf;
        }
    }
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g[x][y]=z;
        g[y][x]=z;
    }
}
void floyd(){
    memcpy(dist1,g,sizeof(dist1));
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(dist1[i][k]+dist1[k][j]<=dist1[i][j]){
                    dist1[i][j]=dist1[i][k]+dist1[k][j];
                }
            }
        }
    }
}
void floyd_max(){
    memcpy(dist2,g,sizeof(dist2));
        for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(dist2[i][j]==inf)dist2[i][j]=-inf;
        }
    }
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int tmp=min(dist2[i][k],dist2[k][j]);
                dist2[i][j]=max(dist2[i][j],tmp);
            }
        }
    }
}
void floyd_min(){
    memcpy(dist3,g,sizeof(dist3));
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int tmp=max(dist3[i][k],dist3[k][j]); 
                dist3[i][j]=min(dist3[i][j],tmp); 
            }
        }
    }
}
int main(){
    init();
    floyd();
    floyd_max();
    floyd_min();
    for(int i=1;i<=q;i++){
        scanf("%d%d",&s,&t);
        printf("%d %d %d\n",dist1[s][t],dist2[s][t],dist3[s][t]);
    }
    return 0;
}

转载于:https://www.cnblogs.com/virtual-north-Illya/p/10045089.html

<think>好的,我现在需要帮用户整理GESP五级相关的所有算法模板合集。首先,用户提到了几个引用,我需要先看看这些引用内容里有什么相关信息。 引用1提到的是GESP202403四级题目,可能和五级关系不大,但用户特别问的是五级,所以可能不需要关注这个。引用2是关于C++五级考试的考,包括贪心算法的性质、区间调度、背包问题等,还提到了练习题如排队接水、线段覆盖、合并果子。这里用户可能需要贪心算法的模板。另外练习建议里提到要掌握基础算法模板,比如高精度、筛法,还有递归分治、链表高精度等。引用3是关于五级编程题,涉及二维前缀和解决矩形面积问题,方法1是O(n^4)的解法,可能还有更优的方法,但用户需要模板,所以可能需要包含二维前缀和的实现。 接下来,我需要回忆GESP五级考试的大纲,通常五级可能涵盖更复杂的算法,比如动态规划、图论基础、贪心算法、搜索算法优化、高级数据结构等。结合引用中的内容,用户可能需要以下算法模板: 1. 贪心算法:比如区间调度、背包问题(可能部分背包)、合并果子(哈夫曼树,优先队列)。 2. 动态规划:背包问题(01背包、完全背包)、最长公共子序列等。 3. 搜索算法:DFS、BFS的优化,剪枝技巧,记忆化搜索。 4. 图论算法:最短路径(Dijkstra、Floyd)、最小生成树(Prim、Kruskal)。 5. 高级数据结构:并查集、优先队列(堆)、线段树等。 6. 基础算法:高精度计算、筛法求素数、递归分治。 7. 前缀和与差分:一维、二维前缀和的应用,如引用3中的题目需要二维前缀和。 然后,我需要确保每个算法都有对应的代码模板,并且符合用户的要求,使用正确的中文注释和格式。例如,贪心算法的区间调度可能需要按结束时间排序;二维前缀和需要预计算然后查询子矩阵的和。 另外,用户可能需要相关练习题,引用2里提到了几个洛谷的题目,比如P1223排队接水,P1803线段覆盖,P1090合并果子,这些可以作为示例。同时,引用3的问题可以用二维前缀和来解决,所以可能需要给出模板的应用示例。 需要注意,用户要求的是算法模板合集,所以每个部分需要简洁的代码示例和关键说明。同时,根据引用2的建议,复杂度分析和代码实现是关键,因此每个模板可能需要包含时间复杂度的说明。 最后,检查是否有遗漏的算法,比如分治递归、链表和高精度的模拟代码,这些在引用2的练习建议中被提到,需要包含进去。例如,高精度加减乘除的模板,链表的基本操作(避免使用STL)等。 总结,需要整理的模板包括: - 贪心算法:区间调度、部分背包、合并果子 - 动态规划:01背包、LCS - 搜索:DFS剪枝、BFS - 图论:Dijkstra、Prim - 数据结构:并查集、优先队列、高精度 - 前缀和:二维前缀和 - 分治递归:快速幂、归并排序 - 其他:筛法求素数 每个部分给出代码示例和简要说明,确保LaTeX格式正确,行内公式用$...$,独立公式用$$...$$,并生成相关问题。</think>### GESP五级算法模板合集 #### 一、贪心算法 1. **区间调度问题** ```python def interval_schedule(intervals): intervals.sort(key=lambda x: x[1]) # 按结束时间排序 count, end = 0, -1 for s, e in intervals: if s >= end: count += 1 end = e return count ``` 关键:证明贪心选择性质成立(每次选最早结束的区间)[^2] 2. **部分背包问题** $$ \text{价值} = \sum \frac{v_i}{w_i} \times \text{剩余容量} $$ ```python def fractional_knapsack(items, capacity): items.sort(key=lambda x: x[0]/x[1], reverse=True) total = 0.0 for v, w in items: if capacity >= w: total += v capacity -= w else: total += v * (capacity / w) break return total ``` #### 二、动态规划 1. **01背包模板** 状态转移方程: $$ dp[i][j] = \max(dp[i-1][j], dp[i-1][j-w_i] + v_i) $$ ```python def knapsack_01(weights, values, capacity): n = len(weights) dp = [0]*(capacity+1) for i in range(n): for j in range(capacity, weights[i]-1, -1): dp[j] = max(dp[j], dp[j-weights[i]] + values[i]) return dp[capacity] ``` #### 三、搜索算法 1. **DFS剪枝模板** ```python def dfs(state): if 终止件: 记录结果 return for 选择 in 所有可能分支: if 剪枝件: continue 更新状态 dfs(新状态) 回溯状态 ``` #### 四、图论算法 1. **Dijkstra最短路径** 时间复杂度:$O((V+E)\log V)$ ```python import heapq def dijkstra(graph, start): dist = {node: float('inf') for node in graph} dist[start] = 0 heap = [(0, start)] while heap: d, u = heapq.heappop(heap) if d > dist[u]: continue for v, w in graph[u].items(): if dist[v] > dist[u] + w: dist[v] = dist[u] + w heapq.heappush(he
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值