【Luogu T145192】 【2020.8.23NOIP模拟赛】最优路线
题目大意:
一个 \(n\) 个点 \(m\) 条边的无重边无自环的无向图,点有点权,边有边权,定义一条路径的权值为路径经过的点权的最大值乘边权最大值。求任意两点间的权值最小的路径的权值。
正文:
一道 Floyd 练手题,存下每条路的最大点权与边权,在 Floyd 的时候一起运算,Floyd 时升序枚举点权作为中点。
代码:
int main()
{
scanf ("%d%d", &n, &m);
memset(mp, 0x7f, sizeof mp);
memset(me, 0x7f, sizeof me);
memset(dis, 0x7f, sizeof dis);
for(int i = 1; i <= n; i++)
scanf("%d", &val[i]), a[i].val = val[i], a[i].id = i;
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= m; i++)
{
int u, v; ll w;
scanf ("%d%d%lld", &u, &v, &w);
me[u][v] = me[v][u] = w;
mp[u][v] = mp[v][u] = max(val[u], val[v]);
vis[u][v] = vis[v][u] = 1;
dis[u][v] = dis[v][u] = (ll)mp[v][u] * me[u][v];
}
for(int K = 1; K <= n; K++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
int k = a[K].id;
if(!vis[i][k] || !vis[k][j] || i == j) continue;
int maxp = max(mp[i][k], mp[k][j]),
maxe = max(me[i][k], me[k][j]);
if((ll)maxp * maxe < dis[i][j])
{
dis[i][j] = (ll)maxp * maxe;
mp[i][j] = maxp;
me[i][j] = maxe;
vis[i][j] = 1;
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if(i == j) printf("0 ");
else if(vis[i][j]) printf("%lld ", dis[i][j]);
else printf("-1 ");
}
puts("");
}
return 0;
}