题目描述
题目
一个 n 个点 m 条边的无重边无自环的无向图,点有点权,边有边权,定义一条路径的权值为路径经过的点权的最大值乘边权最大值。求任意两点间的权值最小的路径的权值。
输入格式
第一行两个整数 n,m,分别表示无向图的点数和边数。
第二行 n 个正整数,第 i 个正整数表示点 i 的点权。
接下来 m 行每行三个正整数 u i,v i ,w i ,分别描述一条边的两个端点和边权。
输出格式
n 行每行 n 个整数,第 i行第 j 个整数表示从 i 到 j 的路径的最小权值,如果从 i 不能到达 j,则该值为 −1。特别地,当 i=j 时输出 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
分析:
r e g i s t e r register register永远滴神!!!
正解还真是为 f l o y e d floyed floyed我傻了?
比赛时我打的就是 f l o y e d floyed floyed 结果没开 l o n g l o n g long long longlong直接滚粗
赛后开了 l o n g l o n g 50 long long50 longlong50分 最后还是开了 O 2 O2 O2优化以及快读 + n +n +n个 r e g i s t e r register register卡过的
f l o y e d floyed floyed过程 :
照点权排序 f l o y e d floyed floyed最外层 k k k枚举的是点权的最大值 然后 i i i与 j j j正常更新边权最小值
判断 i i i与 j j j的点权 < k <k <k 再更新最短路 复杂度还是 O ( n 3 ) O(n^3) O(n3) 时限 2 S 2S 2S 卡卡就过了……
CODE:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#pragma GCC optimize(2)
#define inf 0x7fffffff
using namespace std;
const long long INF=2e18;
int n,m;
inline int read() //快读
{
int X=0; bool flag=1; 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);
}
struct node
{
int value,p; //点权与下标
}a[505];
bool cmp(node x,node y){
return x.value<y.value;
}
int f[505][505];
long long dis[505][505];
int main()
{
int x,y,z;
n=read();m=read();
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++)
{
dis[i][j]=INF;f[i][j]=inf; //赋初值
}
for(register int i=1;i<=n;i++)
{
dis[i][i]=f[i][i]=0; //i=j为0
a[i].value=read();
a[i].p=i; //记录下标
}
for(register int i=1;i<=m;i++)
{
x=read();y=read();z=read();
f[x][y]=f[y][x]=z; //双向邻接矩阵
}
sort(a+1,a+n+1,cmp);
for(register int k=1;k<=n;k++)
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++) //register永远滴神
{
int qwq=a[i].p,qaq=a[j].p,ovo=a[k].p;
f[qwq][qaq]=min(f[qwq][qaq],max(f[qwq][ovo],f[ovo][qaq])); //更新边权最小值
if(i<=k&&j<=k) //点权<k
dis[qwq][qaq]=min(dis[qwq][qaq],1ll*a[k].value*f[qwq][qaq]); //更新最短路
}
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<=n;j++)
if(dis[i][j]!=INF)
printf("%lld ",dis[i][j]);
else
printf("-1 ");
printf("\n");
}
return 0;
}