【2020.8.23NOIP模拟赛】【图论】【最短路】最优路线

41 篇文章 0 订阅
26 篇文章 0 订阅
题目描述

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

输入格式

第一行两个整数 n , m n,m n,m,分别表示无向图的点数和边数。

第二行 n n n个正整数,第 i i i个正整数表示点 i i i的点权。

接下来 m m m行每行三个正整数 u i , v i , w i u_i,v_i,w_i ui,vi,wi​,分别描述一条边的两个端点和边权。

输出格式

n n n行每行 n n n个整数,第 i i i行第 j j j个整数表示从 i i i j j j的路径的最小权值,如果从 i i i不能到达 j j j,则该值为 − 1 -1 1。特别地,当 i = j i=j i=j时输出 0 0 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
说明/提示

对于 20 % 20\% 20%的数据, n ≤ 5 , m ≤ 8 n\le 5,m\le 8 n5,m8

对于 50 % 50\% 50%的数据, n ≤ 50 n\le 50 n50

对于 100 % 100\% 100% 的数据, n ≤ 500 , m ≤ n ( n − 1 ) / 2 n\le 500,m\le n(n-1)/2 n500,mn(n1)/2,边权和点权不超过 1 0 9 10^9 109


解题思路

中心思想Floyd
我也不知道什么Floyd可以做500^3

将点权从小到大排序,保证前面的点权(qwq)比后面的点权小,那么点权更新时才能更优
更新点权时,同时更新边权,蛮暴力的


Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct DT{
	long long s;
	int i;
}a[600];
int n, m, x, y, z;
long long s[600], b[600][600], dis[600][600];
bool cmp (const DT&k, const DT&l){
	return (k.s < l.s);
}
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 (dis, 0x3f, sizeof (dis));
	memset (b, 0x3f, sizeof (b));
	for (register int i = 1; i <= n; i++)
	{
	    s[i] = read ();
	    dis[i][i] = 0;
	    a[i].s = s[i], a[i].i = i;
	}
	sort (a+1, a+1+n, cmp);
    for (register int j = 1; j <= m; j++)
    {
    	x = read (), y = read (), z = read ();
    	b[x][y] = b[y][x] = z;
    	dis[x][y] = dis[y][x] = min(dis[x][y], b[x][y] * max(s[x], s[y]));
    }
    for (register int k = 1; k <= n; k++)
        for (register int i = 1; i <= n; i++)
            for (register int j = 1; j <= n; j++)
            	if (b[i][j] > max (b[i][a[k].i], b[a[k].i][j]))
            	{
            		b[i][j] = max (b[i][a[k].i], b[a[k].i][j]);
            		dis[i][j] = min (dis[i][j], b[i][j] * max (a[k].s, max (s[i],s[j])));
            	}
    for (register int i = 1; i <= n; i++,printf("\n"))
        for (register int j = 1; j <= n; j++)
            if (i == j) printf ("0 ");
               else if (dis[i][j] == 0) printf ("-1 ");
                       else printf ("%lld ",dis[i][j]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
寻找无向图最优回路通常可以使用旅行商问题(Traveling Salesman Problem,TSP)的算法来解决。TSP是一种经典的组合优化问题,它的目标是在给定的一组城市(图中的节点)之间找到一条最短的路径,使得每个城市恰好被访问一次,并回到起始城市。 在Python中,可以使用一些第三方库来解决TSP问题,例如使用PyTSP库。PyTSP是一个基于Python的TSP求解器,它实现了多种TSP求解算法,包括贪心算法、蚁群算法、模拟退火算法等。 下面是一个使用PyTSP库求解无向图最优回路的示例代码: ```python from pytsp import TravelingSalesmanProblem import networkx as nx # 构建无向图 G = nx.Graph() G.add_edge(0, 1, weight=2) G.add_edge(0, 2, weight=3) G.add_edge(0, 3, weight=5) G.add_edge(1, 2, weight=4) G.add_edge(1, 3, weight=6) G.add_edge(2, 3, weight=1) # 定义TSP问题 tsp = TravelingSalesmanProblem() # 添加节点和边 for node in G.nodes: tsp.add_node(node) for u, v, weight in G.edges.data('weight'): tsp.add_edge(u, v, weight) # 求解TSP问题 tsp.tour() # 输出结果 print(tsp.best_tour_cost) print(tsp.best_tour) ``` 在上面的代码中,我们首先使用networkx库构建了一个包含6个节点和6条边的无向图,然后使用PyTSP库定义了一个TSP问题,并将图中的节点和边添加到TSP问题中。最后,我们调用tsp.tour()方法求解TSP问题,并输出最优回路的长度和节点顺序。 需要注意的是,TSP问题是NP难问题,因此对于大规模的问题,即使使用最优的算法也可能需要很长时间才能得到结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值