【2020.8.23NOIP模拟赛】最优路线

题目描述

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

思路:

这题定义两个dis,分别表示路径长度和答案,如果大于的话就更新
最后注意:这题n<=500,Floyd不卡会炸,所以要经过一番神奇卡常

代码:

#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

int n, m;
int x, y, w;
int v[510];
long long dis[501][501], dis2[501][501];
struct node{
     
	int x, y;
}a[1000001];
inline 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);
}
inline void print(long long x) {
     
    if(x<0)putchar('-'),x=-x;
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
inline bool cmp(const node&x,const node&y)
{
     
	return x.x<y.x;
}
int main(){
     
	n=read();
	m=read();
	memset(dis, 127, sizeof(dis));
	memset(dis2, 127, sizeof(dis2));
	for(register int i=1; i<=n; ++i)
	{
     
		v[i]=read();
		a[i].x=v[i];
		a[i].y=i;
		dis[i][i]=0;
	}
	for(register int i=1; i<=m; ++i)
	{
     
		x=read();
		y=read();
		w=read();
		dis2[x][y]=dis2[y][x]=w;
		dis[x][y]=dis[y][x]=min(dis[x][y], dis2[x][y]*max(v[x], v[y]));
	}
	sort(a+1, a+1+n, cmp);
	for(register int k1=1; k1<=n; ++k1)
	{
     
		register int k=a[k1].y;
		for(register int i=1; i<=n; ++i)
			for(register int j=1; j<=n; ++j)
			{
     
				if(dis2[i][j]>max(dis2[i][k], dis2[j][k])){
     
					dis2[i][j]=max(dis2[i][k], dis2[j][k]);
					dis[i][j]=min(dis[i][j], dis2[i][j]*(max(v[i], max(v[j], v[k]))));
				}
			}
	}
	for(register int i=1; i<=n; ++i)
	{
      
		for(register int j=1; j<=n; ++j)
		{
     
			if(i==j)
				print(0);
			else if(dis2[i][j]==0) 
				print(-1);
			else print(dis[i][j]);
			putchar(32);
		}
		printf("\n");
	} 
}

你可能感兴趣的:(题解,Floyed)