spfa的最小生成树~

最小生成树算法在图论中的应用

B - 基础
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected. 

We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.

Input

The first line is an integer N (3 <= N <= 100), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 1000]) between village i and village j. 

Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.

Output

You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum.

Sample Input

3
0 990 692
990 0 179
692 179 0
1
1 2

Sample Output

179

这个可以利用spfa计算最小生成树 模板....



#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

#define N 210
#define d double
#define INF 0xffffff
int n;
int visit[N];
d dis[N],len[N][N];
d a,b,c;

struct node
{
	d x,y;
}s[N];

double wal(int i,int j)
{
    d length=sqrt(((d)s[i].x-(d)s[j].x)*((d)s[i].x-(d)s[j].x)+((d)s[i].y-(d)s[j].y)*((d)s[i].y-(d)s[j].y));
    return 60*length/10000.0 ;
}
double sub(int i,int j)
{
    d length=sqrt(((d)s[i].x-(d)s[j].x)*((d)s[i].x-(d)s[j].x)+((d)s[i].y-(d)s[j].y)*((d)s[i].y-(d)s[j].y));
    return 60*length/40000.0;
}

void clean()
{
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		len[i][j]=-1;
}

void SPFA()
{
	memset(visit,0,sizeof(visit));
	for(int i=0;i<=n;i++)
		dis[i]=INF;
	visit[1]=1;
	dis[1]=0;
	queue<int>que;
	que.push(1);
	while(!que.empty())
	{
		int t=que.front();
		for(int i=1;i<=n;i++)
		{
			if(len[t][i]!=-1 && dis[i]>dis[t]+len[t][i])
			{
				dis[i]=dis[t]+len[t][i];
				if(visit[i]==0)
				{
					visit[i]=1;
					que.push(i);
				}
			}
		}
		que.pop();
		visit[t]=0;
	}
}

int main()
{
	scanf("%lf %lf %lf %lf",&s[1].x,&s[1].y,&s[2].x,&s[2].y);
	len[1][2]=len[2][1]=wal(1,2);
	n=3;c=0;
	while(~scanf("%lf %lf",&a,&b))
	{
		if(a==-1 && b==-1)
		{
			c=0;
		}
		else
		{
			s[n].x=a;
		    s[n].y=b;
		    for(int i=1;i<n-c;i++)
				len[i][n]=len[n][i]=wal(i,n);
		    for(int i=n-c;i<n;i++)
			    len[i][n]=len[n][i]=sub(i,n);
		    c=1;
		    n++;
		}
	}
	n--;
	SPFA();
	printf("%.0lf\n",dis[2]);
    return 0;
}




### 最小生成树算法与最短路径算法的实现及区别 #### 一、最小生成树算法概述 最小生成树(Minimum Spanning Tree, MST)是一种用于无向加权连通图的经典算法,其目标是在保证所有节点联通的前提下找到总权重最小的一组边集合。常见的两种经典算法分别是 **Prim 算法** 和 **Kruskal 算法**。 - Prim 算法的核心思想是以某个起始节点为基础逐步扩展一棵树,在每一步中选择当前未加入树中的最近邻接点作为新的节点加入树中[^1]。 - Kruskal 算法则是基于全局视角,先将所有边按权重从小到大排序,再依次选取不会形成环路的边来构建最终的生成树[^3]。 以下是 Prim 算法的一个 Python 实现: ```python import heapq def prim(graph, start): mst = [] visited = set() edges = [(0, start, None)] while edges: weight, node, parent = heapq.heappop(edges) if node not in visited: visited.add(node) if parent is not None: mst.append((parent, node, weight)) for neighbor, cost in graph[node]: if neighbor not in visited: heapq.heappush(edges, (cost, neighbor, node)) return mst ``` #### 二、最短路径算法概述 最短路径问题旨在寻找从某一特定起点到达其他各点或者某一点之间的最短路径长度。其中经典的 Dijkstra 算法适用于非负权重图的情况,通过维护一个优先队列不断更新当前已知的最短路径估计值直到达到终止条件为止[^2]。 下面是 Dijkstra 算法的一种简单实现方式: ```python import heapq def dijkstra(graph, start): distances = {node: float('infinity') for node in graph} distances[start] = 0 priority_queue = [(0, start)] while priority_queue: current_distance, current_node = heapq.heappop(priority_queue) if current_distance > distances[current_node]: continue for neighbor, weight in graph[current_node].items(): distance = current_distance + weight if distance < distances[neighbor]: distances[neighbor] = distance heapq.heappush(priority_queue, (distance, neighbor)) return distances ``` #### 三、两者的区别分析 尽管两者均采用了某种形式的贪心策略来进行优化决策,但在具体应用场景以及解决问题的目标上存在显著差异: 1. **目的不同**: 最小生成树关注的是如何以最低成本连接整个网络内的全部结点;而最短路径则专注于发现由单一源头通往其余各个目的地间的最优路线。 2. **适用范围各异**: 对于含有负权回路的情形下,Dijkstra 将失效,需改用 Bellman-Ford 或 SPFA 方法处理此类情况。然而无论是否存在正数还是零值循环结构都不会影响MST计算结果的有效性[^2]. 3. **数据结构需求有所差别**: 在执行过程中,Dijkstra 需要频繁访问并调整距离表项以便及时反映最新估算进展状况;相比之下,Prim 更多地依赖堆栈操作完成候选元素筛选工作. 4. **时间复杂度对比**: 假设采用斐波那契堆辅助加速版本的话,则理论上可以分别获得 O(E+VlogV) 的运行效率针对稀疏型拓扑结构下的SPFA/Dijksra实例而言,而对于稠密情形来说可能更倾向于选用矩阵乘方技术改进后的Floyd-Warshall方案替代原始朴素迭代模式下的O(V³). --- 问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值