题目描述
一个 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。
输入输出样例
输入 #1
3 3
2 3 3
1 2 2
2 3 3
1 3 1
输出 #1
0 6 3
6 0 6
3 6 0
说明/提示
对于 20 % 20\% 20%的数据, n ≤ 5 , m ≤ 8 n\le 5,m\le 8 n≤5,m≤8。
对于 50 % 50\% 50%的数据, n ≤ 50 n\le 50 n≤50。
对于 100 % 100\% 100% 的数据, n ≤ 500 , m ≤ n ( n − 1 ) / 2 n\le 500,m\le n(n-1)/2 n≤500,m≤n(n−1)/2,边权和点权不超过 1 0 9 10^9 109。
解题思路
中心思想Floyd
我也不知道什么Floyd可以做500^3
将点权从小到大排序,保证前面的点权(qwq)比后面的点权小,那么点权更新时才能更优
更新点权时,同时更新边权,蛮暴力的
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct DT{
long long s;
int i;
}a[600];
int n, m, x, y, z;
long long s[600], b[600][600], dis[600][600];
bool cmp (const DT&k, const DT&l){
return (k.s < l.s);
}
int read()
{
register int X=0;register bool flag=1; register char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
int main(){
n = read (), m = read ();
memset (dis, 0x3f, sizeof (dis));
memset (b, 0x3f, sizeof (b));
for (register int i = 1; i <= n; i++)
{
s[i] = read ();
dis[i][i] = 0;
a[i].s = s[i], a[i].i = i;
}
sort (a+1, a+1+n, cmp);
for (register int j = 1; j <= m; j++)
{
x = read (), y = read (), z = read ();
b[x][y] = b[y][x] = z;
dis[x][y] = dis[y][x] = min(dis[x][y], b[x][y] * max(s[x], s[y]));
}
for (register int k = 1; k <= n; k++)
for (register int i = 1; i <= n; i++)
for (register int j = 1; j <= n; j++)
if (b[i][j] > max (b[i][a[k].i], b[a[k].i][j]))
{
b[i][j] = max (b[i][a[k].i], b[a[k].i][j]);
dis[i][j] = min (dis[i][j], b[i][j] * max (a[k].s, max (s[i],s[j])));
}
for (register int i = 1; i <= n; i++,printf("\n"))
for (register int j = 1; j <= n; j++)
if (i == j) printf ("0 ");
else if (dis[i][j] == 0) printf ("-1 ");
else printf ("%lld ",dis[i][j]);
}