【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; 
 
}

原文地址:https://www.cnblogs.com/GJY-JURUO/p/13550469.html