【最短路】UVa10048 噪音 (floyd求min/max问题)

本文探讨了一个从A点到B点的路径问题,目标是在所有路径中找到一条,其上所有噪音中最大的值是最小的。通过Floyd算法的修改,实现了这一复杂路径查找任务。

题目

从a点到b点, 找到一条路径,使得这条路径上的所有噪音中最大的值是所有路径中最小的, 这个噪音值便是要求的。

思路

首先询问次数较多,考虑多源。这个路径结点最大值最小问题,其实类似于最短路,floyd改一下即可。

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int INF = 1000000000;
const int maxn = 100+10;
int n, m, q, d[maxn][maxn];

int main(){
    int kase = 0;
    while(scanf("%d%d%d",&n,&m,&q) == 3 && n){
        int u,v,w;
        _rep(i,1,n) _rep(j,1,n) if (i != j) d[i][j] = INF;
        _for(i,0,m){
            scanf("%d%d%d",&u,&v,&w);
            d[u][v] = w;
            d[v][u] = w;
        }
        _rep(k,1,n)
            _rep(i,1,n)
                _rep(j,1,n)
                    d[i][j] = min(d[i][j], max(d[i][k], d[k][j]));

        if (kase) printf("\n");
        printf("Case #%d\n",++kase);
        _for(i,0,q){
            scanf("%d%d",&u,&v);
            if (d[u][v] == INF) printf("no path\n");
            else printf("%d\n",d[u][v]);
        }
        //printf("\n");
    }
}
Floyd算法通常用于计算图中所有点对之间的短路径,但它本身并不直接提供路径方案数量的统计功能。若要在使用Floyd算法短路径的同时统计路径方案数,可以通过扩展算法逻辑实现。 具体方法如下: 在初始化距离矩阵 `d[i][j]` 的基础上,增加一个路径计数矩阵 `cnt[i][j]`,用于记录从节点 `i` 到节点 `j` 的短路径数量。初始时,每对节点之间的路径数量默认为 0,而直接存在边的节点对则设置为 1,表示存在一条直接路径[^3]。 算法的主要步骤如下: 1. **初始化**: - `d[i][j]` 表示从节点 `i` 到节点 `j` 的短路径长度,初始化为边的权重。 - `cnt[i][j]` 表示从节点 `i` 到节点 `j` 的短路径数量,初始化为直接路径的数量。 2. **动态更新**: - 在Floyd算法的三重循环中,当发现通过中间节点 `k` 的路径 `d[i][k] + d[k][j]` 等于当前路径长度 `d[i][j]` 时,说明找到了一条新的等长路径,此时更新 `cnt[i][j] += cnt[i][k] * cnt[k][j]`。 - 如果通过中间节点 `k` 的路径 `d[i][k] + d[k][j]` 小于当前路径长度 `d[i][j]`,则更新短路径长度 `d[i][j] = d[i][k] + d[k][j]`,同时更新路径数量 `cnt[i][j] = cnt[i][k] * cnt[k][j]`。 ### 示例代码 ```cpp #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 210, INF = 1e9; int n, m, Q; int d[N][N]; // 距离矩阵 int cnt[N][N]; // 路径计数矩阵 void floyd() { for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (d[i][k] + d[k][j] < d[i][j]) { d[i][j] = d[i][k] + d[k][j]; cnt[i][j] = cnt[i][k] * cnt[k][j]; } else if (d[i][k] + d[k][j] == d[i][j]) { cnt[i][j] += cnt[i][k] * cnt[k][j]; } } } } } int main() { cin >> n >> m >> Q; // 初始化距离矩阵和路径计数矩阵 for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i == j) { d[i][j] = 0; cnt[i][j] = 1; } else { d[i][j] = INF; cnt[i][j] = 0; } } } // 输入边信息 while (m--) { int a, b, c; cin >> a >> b >> c; if (d[a][b] > c) { d[a][b] = c; cnt[a][b] = 1; } else if (d[a][b] == c) { cnt[a][b]++; } } floyd(); // 查询短路径和路径数量 while (Q--) { int a, b; cin >> a >> b; if (d[a][b] == INF) { cout << "impossible" << endl; } else { cout << "Shortest distance: " << d[a][b] << endl; cout << "Number of paths: " << cnt[a][b] << endl; } } return 0; } ``` 该代码在Floyd算法的基础上,增加了路径计数矩阵 `cnt[i][j]`,并根据路径更新规则,动态维护短路径的数量。 ### 相关问题 1. 如何通过Floyd算法构造短路径的具体路径? 2. 在Floyd算法中如何处理负权边? 3. 如何优化Floyd算法的时间复杂度? 4. Floyd算法与Dijkstra算法在多源短路问题中的区别是什么? 5. 如何使用Floyd算法检测图中的负权环?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值