【洛谷2020.8.23日SSL模拟赛T2】最优路线【Floyed最短路变式】

题目描述

题目
一个 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;
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/108187329
今日推荐