P1629 邮递员送信

邮递员最短路径问题的Dijkstra算法解决方案,

题目描述

有一个邮递员要送东西,邮局在节点 1。他总共要送 n−1 样东西,其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n−1 样东西并且最终回到邮局最少需要的时间。

输入格式

第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。

第二行到第 (m+1) 行,每行三个整数,u,v,w 表示从 u 到 v 有一条通过时间为 w 的道路。

输出格式

输出仅一行,包含一个整数,为最少需要的时间。

输入输出样例

输入
5 10
2 3 5
1 5 5
3 5 6
1 2 8
1 3 8
5 3 4
4 1 8
4 5 3
3 5 6
5 4 2
输出
83

这一看就是用单源最短路径求解答案,首先去第2到n个节点就不用说了,就是1到每个点的最短路径,这个在单元最短路里面讲过,接着就要看走回来这个问题

走回来怎么弄,以2到n每个点为根据点求出最短路径?这样肯定不行,TLE等着你

那怎么弄,其实仔细想一想,就不难想到,我们可以把有向图反过来存,还是以1为基础求单元最短路,dis里面存的就是2到n距离1的最短路了

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e3+5;
int n,m;
struct node{
	int to,dis;
	friend bool operator <(node a,node b){
		return a.dis>b.dis;
	}
};
vector<node> a[N];
vector<node> b[N];
int dis[N];
int dis2[N];
int vis[N];
int vis2[N];
int s;
priority_queue<node>q1;
priority_queue<node>q2;
void dij_start(){
	for(int i=1;i<=n;i++)dis[i]=INT_MAX;
	dis[s]=0;
	q1.push(node{s,0});
	while(!q1.empty()){
		node t=q1.top();
		q1.pop();
		int x=t.to;
		if(vis[x]==1)continue;
		vis[x]=1;
		for(int i=0;i<a[x].size();i++){
			int y=a[x][i].to;
			int z=a[x][i].dis;
			dis[y]=min(dis[y],dis[x]+z);
			if(vis[y]==0)q1.push(node{y,dis[y]});
		}
	}
}
void dij_over(){
	for(int i=1;i<=n;i++)dis2[i]=INT_MAX;
	dis2[s]=0;
	q2.push(node{s,0});
	while(!q2.empty()){
		node t=q2.top();
		q2.pop();
		int x=t.to;
		if(vis2[x]==1)continue;
		vis2[x]=1;
		for(int i=0;i<b[x].size();i++){
			int y=b[x][i].to;
			int z=b[x][i].dis;
			dis2[y]=min(dis2[y],dis2[x]+z);
			if(vis2[y]==0)q2.push(node{y,dis2[y]});
		}
	}
}
signed main(){
	scanf("%lld%lld",&n,&m);
	int u,v,w;
	for(int i=1;i<=m;i++){
		scanf("%lld%lld%lld",&u,&v,&w);
		a[u].push_back(node{v,w});
		b[v].push_back(node{u,w});
	}
	s=1;
	dij_start();
	dij_over();
	int sum=0;
	for(int i=2;i<=n;i++)sum+=dis[i]+dis2[i];
	printf("%lld",sum);
}

### Python 实现邮递员送信功能的模拟 要实现类似于“邮递员送信”的功能,可以将其抽象为旅行商问题 (Traveling Salesman Problem, TSP)[^1] 或者最短路径问题[^4]。这类问题是经典的组合优化问题之一,在实际应用中可以通过多种算法来求解。 #### 使用遗传算法解决 TSP 问题 一种常见的方法是采用 **遗传算法** 来寻找近似最优解。以下是基于遗传算法的一个简化版本: ```python import random import numpy as np def generate_cities(num_cities): """随机生成城市的坐标""" cities = {i: (random.uniform(0, 1), random.uniform(0, 1)) for i in range(num_cities)} return cities def calculate_distance(city_a, city_b): """计算两个城市之间的欧几里得距离""" xa, ya = city_a xb, yb = city_b return ((xa - xb)**2 + (ya - yb)**2)**0.5 def fitness_function(individual, cities): """适应度函数:总路程越短越好""" total_distance = 0 for idx in range(len(individual)): from_city_idx = individual[idx] to_city_idx = individual[(idx + 1) % len(individual)] total_distance += calculate_distance(cities[from_city_idx], cities[to_city_idx]) return 1 / total_distance def crossover(parent1, parent2): """单点交叉操作""" point = random.randint(0, len(parent1)) child = [-1] * len(parent1) # 复制父代的部分基因到子代 child[:point] = parent1[:point] # 填充剩余部分 pointer = point while any(x == -1 for x in child): if parent2[pointer] not in child: first_empty_position = child.index(-1) child[first_empty_position] = parent2[pointer] pointer = (pointer + 1) % len(parent2) return child def mutate(individual, mutation_rate=0.01): """变异操作""" for swap_i in range(len(individual)): if random.random() < mutation_rate: swap_j = int(random.random() * len(individual)) individual[swap_i], individual[swap_j] = individual[swap_j], individual[swap_i] return individual def genetic_algorithm(population_size, num_generations, num_cities, mutation_rate=0.01): """遗传算法主程序""" cities = generate_cities(num_cities) population = [list(np.random.permutation(list(range(num_cities)))) for _ in range(population_size)] best_individual = None best_fitness = float('-inf') for generation in range(num_generations): new_population = [] # 计算当前种群的适应度并选择优秀个体 fitness_scores = [(fitness_function(indiv, cities), indiv) for indiv in population] sorted_population = [indiv for _, indiv in sorted(fitness_scores, key=lambda x: x[0], reverse=True)] current_best = sorted_population[0] current_best_fitness = fitness_function(current_best, cities) if current_best_fitness > best_fitness: best_fitness = current_best_fitness best_individual = current_best # 进行繁殖过程 elite_count = max(int(0.1 * population_size), 1) # 精英策略保留前几名 new_population.extend(sorted_population[:elite_count]) while len(new_population) < population_size: parent1 = random.choice(sorted_population[:int(population_size*0.3)]) # 更倾向于选优胜个体 parent2 = random.choice(sorted_population[int(population_size*0.7):]) offspring = crossover(parent1, parent2) mutated_offspring = mutate(offspring, mutation_rate) new_population.append(mutated_offspring) population = new_population return best_individual, best_fitness, cities if __name__ == "__main__": result_path, result_fitness, generated_cities = genetic_algorithm( population_size=100, num_generations=500, num_cities=10, mutation_rate=0.01 ) print("最佳路径:", result_path) print("适应度分数(倒数总距离):", result_fitness) ``` 上述代码实现了通过遗传算法找到一条接近于全局最优的路径。其中的关键步骤包括: - 编码阶段:将每条可能的路径表示为一个排列数组。 - 解码阶段:根据该排列计算对应的路径长度作为目标函数的一部分。 - 遗传操作:包括选择、交叉和变异三个主要环节。 #### 关键概念解释 - **编码与解码**: 将问题中的可行解转化为计算机可处理的形式[^2]。 - **适应度函数**: 定义衡量解决方案质量的标准,通常是最小化或最大化某个指标。 - **遗传操作**: 包括选择更优秀的个体参与下一代繁衍以及引入一定的随机性以探索新的可能性。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值