N个点,M条边,每条边有权值。求一条1号点到N号点的路径,要求使得路径中的边权最小值最大。
Input
多组输入,第一行给一个T。
每一组第一行给两个数n和m。(1 <= n <= 1000)
接下来m行,每行三个数u,v,w代表路径的两个端点与边权。
(1 <= u,v <= n , 0< w <= 1e6)
保证两点间只有一条边,该图为无向图。
Output
第i组数据先输出 “Scenario #i:”
然后输出该路径上的最小边权。
保证有解
Sample Input
1
3 3
1 2 3
1 3 4
2 3 5
Sample Output
Scenario #1:
4
一开始题目里的求路径边权最小值最大属实把我整晕了,到底是最大还是最小呢?
花了一段时间终于开窍了,最小值最大 就是 某条路径的最短边权 比 其他所有路径最短边权都大。
题意理解了于是开始写,脑子马上浮现出一条思路:**最长路径的最短边权不就是最小值最大吗? **于是马上交了一发,出乎意料的 wa 了(这是错误思路!!!)。
一番思考后:最短路径的最短边权 也不一定 是所有路径中最短的边权,最长路径也同理
而且可以运用迪杰斯特拉算法走一步看一步的思想求出源点到所有点路径上最短边权的最大值
只需要做一些小小的改动,代码如下:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
const ll N = 1e10;
using namespace std;
ll mp[1024][1024] = {0}, l[1024] = {0};
int main()
{
ll t;
while(scanf("%lld",&t) != EOF)
{
ll sum = 1;
while(t--)
{
ll n, m;
scanf("%lld%lld",&n, &m);
for(ll i = 1; i <= n; i++)
{
for(ll j = 1; j <= n; j++)
{
if(i == j)
mp[i][j] = 0;
else
mp[i][j] = -N; // 要求的是最大的所以改成 -N
}
}
for(ll i = 1; i <= m; i++)
{
ll v, u, w;
scanf("%lld%lld%lld",&v, &u, &w);
mp[v][u] = mp[u][v] = w;
}
ll judge[1024] = {0}, k, maxx;
for(ll i = 1; i <= n; i++)
{
l[i] = mp[1][i];
}
l[1] = 0;
judge[1] = 1;
for(ll i = 2; i <= n; i++)
{
maxx = -N; // maxx 初始化也同样为 -N
for(ll j = 1; j <= n; j++)
if(!judge[j] && l[j] > maxx) // 此处 小于 改成 大于
{
maxx = l[j];
k = j;
}
judge[k] = 1;
for(ll j = 1; j <= n; j++)
{
if(!judge[j])
{
l[j] = max(l[j], min(maxx, mp[k][j]));// 此处为核心部分
}
}
}
printf("Scenario #%lld:\n%lld\n\n",sum++,l[n]);
}
}
return 0;
}
l[j] = max(l[j], min(maxx, mp[k][j]));// 此处为核心部分
min(maxx, mp[k][j]) 表示:
max(l[j], min(maxx, mp[k][j]))