最优路线

最优路线 ⁡ \operatorname{最优路线} 线

题目链接: luogu T145192 ⁡ \operatorname{luogu\ T145192} luogu T145192 / SSL比赛 1514 ⁡ \operatorname{SSL比赛\ 1514} SSL 1514

题目

一个 n n n 个点 m m m 条边的无重边无自环的无向图,点有点权,边有边权,定义一条路径的权值为路径经过的点权的最大值乘边权最大值。求任意两点间的权值最小的路径的权值。

输入

第一行两个整数 n , m n,m n,m ,分别表示无向图的点数和边数。
第二行 n n n 个正整数,第 i i i 个正整数表示点 i i i 的点权。
接下来 m m m 行每行三个正整数 u i , v i , w i u_i,v_i,w_i ui,vi,wi ,分别描述一条边的两个端点和边权。

输出

n n n 行每行 n n n 个整数,第 i i i 行第 j j j 个整数表示从 i i i j j j 的路径的最小权值,如果从 i i i 不能到达 j j j ,则该值为 − 1 -1 1 。特别地,当 i = j i=j i=j 时输出 0 0 0

样例输入

3 3 
2 3 3 
1 2 2 
2 3 3 
1 3 1 

样例输出

0 6 3 
6 0 6 
3 6 0

数据范围

对于 20 % 20\% 20% 的数据, n ≤ 5 , m ≤ 8 n\le 5,m\le 8 n5,m8

对于 50 % 50\% 50% 的数据, n ≤ 50 n\le 50 n50

对于 100 % 100\% 100% 的数据, n ≤ 500 , m ≤ n ( n − 1 ) / 2 n\le 500,m\le n(n-1)/2 n500,mn(n1)/2 ,边权和点权不超过 1 0 9 10^9 109

思路

这道题是一道 Floyed 最短路。

我们可以看出边权我们可以直接 Floyed 搞,但是点权呢?
我们可以发现,如果我们把点按点权从小到大排,按这个顺序作为中转站,我们就会发现,新的路径的最大点权一定是这个点或者之前两边的求出来的点。那就通过这个来做 Floyed ,就可以得出答案了。

不过 n 3 n^3 n3 500 500 500 需要压一下时间。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rr register
#define ll long long

using namespace std;

struct node {
    
    
	ll x, num;
}a[501];
ll n, m, b[501], x, y, z, f[501][501], dis[501][501];

bool cmp(node x, node y) {
    
    
	return x.x < y.x;
}

ll read() {
    
    //快读
	ll an = 0, zhengfu = 1;
	char c = getchar();
	while (c < '0' || c > '9') {
    
    
		if (c == '-') zhengfu = -zhengfu;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
    
    
		an = an * 10 + c - '0';
		c = getchar();
	}
	return an * zhengfu;
}

int main() {
    
    
	memset(f, 0x7f, sizeof(f));//初始化
	memset(dis, 0x7f, sizeof(dis));
	
	n = read();//读入
	m = read();
	for (rr ll i = 1; i <= n; i++) {
    
    
		f[i][i] = 0;//初始化
		
		b[i] = a[i].x = read();//读入
		a[i].num = i;//初始化
	}
	
	sort(a + 1, a + n + 1, cmp);//按边权排序
	
	for (rr ll i = 1; i <= m; i++) {
    
    
		x = read();//读入
		y = read();
		z = read();
		dis[x][y] = dis[y][x] = z;//求出直接距离和权值
		f[x][y] = f[y][x] = min(f[x][y], dis[x][y] * max(b[x], b[y]));
	}
	
	for (rr ll k = 1; k <= n; k++)//floyed算法
		for (rr ll i = 1; i <= n; i++)
			for (rr ll j = 1; j <= n; j++)
				if (dis[i][j] > max(dis[i][a[k].num], dis[a[k].num][j])) {
    
    
					dis[i][j] = max(dis[i][a[k].num], dis[a[k].num][j]);
					f[i][j] = min(f[i][j], dis[i][j] * (ll)max(b[i], max(b[j], b[a[k].num])));
				}
	
	for (rr ll i = 1; i <= n; i++) {
    
    
		for (rr ll j = 1; j <= n; j++)
			if (i == j) printf("0 ");//输出
				else if (f[i][j] == 0) printf("-1 ");
					else printf("%lld ", f[i][j]);
		printf("\n");
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43346722/article/details/108199801