【洛谷_T145192】【2020.8.23NOIP模拟赛】最优路线

【2020.8.23NOIP模拟赛】最优路线


题目描述

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

输入

第一行两个整数 n,m,分别表示无向图的点数和边数。
第二行 n 个正整数,第 i 个正整数表示点 i 的点权。
接下来 m 行每行三个正整数 ui,vi,wi,分别描述一条边的两个端
输出
n 行每行 n 个整数,第 i 行第 j 个整数表示从 i 到 j 的路径的最小
权值,如果从 i 不能到达 j,则该值为-1。特别地,当 i=j 时输出 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%的数据,n<=5,m<=8。
对于 50%的数据,n<=50
对于 100%的数据,n<=500,m<=n*(n-1)/2,边权和点权不超过 10^9。

解题思路

看到数据,我的第一反应是正解时间复杂度O(n2),然鹅正解竟然是O(n3)的Floyd!!!
这真的是惊到我了 (虽然比赛我用的就是这个,结果没有开long long,直接爆0,开了以后也才20分)
其实正解就是Floyd的变种,加一堆奇奇怪怪的东西(如:快读、O2、register等)就差不多能过了
下附代码:

#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n,m;
long long c[510],b[510][510],d[510][510];

struct abc{
    
    
	int x,y;
}a[100010];

bool hh(abc x,abc y)
{
    
    
	return x.x<y.x;
}

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(d,127,sizeof(d));
	memset(b,127,sizeof(b));
	for(register int i=1;i<=n;++i)
	{
    
    
		c[i]=read();
		b[i][i]=0;
		a[i].x=c[i];
		a[i].y=i;
	}
	for(register int i=1,x,y,w;i<=m;++i)
	{
    
    
		x=read();
		y=read();
		w=read();
		d[x][y]=d[y][x]=w;
		b[x][y]=b[y][x]=min(b[x][y],d[y][x])*max(c[x],c[y]);
	}
	sort(a+1,a+n+1,hh);
	for(register int k=1;k<=n;k++)
	{
    
    
		register int s=a[k].y;
		for(register int i=1;i<=n;i++)
			for(register int j=1;j<=n;j++)
				if(d[i][j]>max(d[i][s],d[s][j]))
				{
    
    
					d[i][j]=max(d[i][s],d[s][j]);
					b[i][j]=min(b[i][j],d[i][j]*max(c[s],max(c[i],c[j])));
				}
	}
	for(register int i=1;i<=n;i++)
	{
    
    
		for(register int j=1;j<=n;j++)
		{
    
    
			if(i==j)
				printf("0");
			else
				if(d[i][j]==0)
					printf("-1");
			else
				printf("%lld",b[i][j]);
			putchar(32);
		}
		printf("\n");
	}
}

猜你喜欢

转载自blog.csdn.net/SSL_guyixin/article/details/108187957