SPOJ 15. The Shortest Path 堆优化Dijsktra

You are given a list of cities. Each direct connection between two cities has its transportation cost (an integer bigger than 0). The goal is to find the paths of minimum cost between pairs of cities. Assume that the cost of each path (which is the sum of costs
of all direct connections belongning to this path) is at most 200000. The name of a city is a string containing characters a,...,z and is at most 10 characters long.

Input

s [the number of tests <= 10]
n [the number of cities <= 10000]
NAME [city name]
p [the number of neighbours of city NAME]
nr cost [nr - index of a city connected to NAME (the index of the first city is 1)]
           [cost - the transportation cost]
r [the number of paths to find <= 100]
NAME1 NAME2 [NAME1 - source, NAME2 - destination]
[empty line separating the tests]

Output

cost [the minimum transportation cost from city NAME1 to city NAME2 (one per line)]

Example

Input:
1
4
gdansk
2
2 1
3 3
bydgoszcz
3
1 1
3 1
4 4
torun
3
1 3
2 1
4 1
warszawa
2
2 4
3 1
2
gdansk warszawa
bydgoszcz warszawa

Output:
3
2

使用堆优化Dijsktra的代码都是一大坨的,写起来好累。

要求对堆和图论和Dijsktra算法都十分熟悉。

这次写了两个多小时,终于过了,这样的题目对思维锻炼是十分有帮助的。

优先熟悉堆的主要函数有:

1 堆中的元素增加和减少值的操作

2 取出堆顶值的操作

灵活改动Dijsktra,只是求两点之间的最短路径。

之前使用指针写过,这次使用静态数组和vector来表示邻接表来解决,不用指针动态分配内存,速度更加快点。

Heap的操作全部用class封装起来了。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string>
#include <map>
#include <vector>
#include <string.h>

using namespace std;
const int MAX_C = 15;
const int MAX_N = 10005;

struct Node
{
	int des, cost;
};
vector<Node> gra[MAX_N];

void insertNeighbor(int src, int des, int cost)
{
	Node n;
	n.cost = cost;
	n.des = des;
	gra[src].push_back(n);
}

struct hNode
{
	int ver, dis;
};
hNode heaps[MAX_N];
int hPos[MAX_N];//指示顶点在堆中的位置

class MinHeap
{
public:
	int size;
	MinHeap(int s = 0): size(s) {}

	int lson(int rt) { return rt<<1; }
	int rson(int rt) { return rt<<1 | 1; }
	int parent(int rt) { return rt>>1; }

	void swaphNode(int l, int r)
	{
		hNode t = heaps[l];
		heaps[l] = heaps[r];
		heaps[r] = t;

		hPos[heaps[r].ver] = r;
		hPos[heaps[l].ver] = l;
	}

	void pushUp(int rt)
	{
		while (parent(rt) > 0 && heaps[parent(rt)].dis > heaps[rt].dis)
		{
			swaphNode(rt, parent(rt));
			rt = parent(rt);
		}
	}

	void pushDown(int rt)
	{
		int l = lson(rt);
		if (l > size) return ;
		int r = rson(rt);

		int sma = rt;
		if (heaps[sma].dis > heaps[l].dis) sma = l;
		if (r <= size && heaps[sma].dis > heaps[r].dis) sma = r;

		if (sma != rt)
		{
			swaphNode(sma, rt);
			pushDown(sma);
		}
	}

	void increase(int ver, int dis)
	{
		int rt = hPos[ver];
		heaps[rt].dis = dis;

		pushDown(rt);
	}

	void decrease(int ver, int dis)
	{
		int rt = hPos[ver];
		heaps[rt].dis = dis;

		pushUp(rt);
	}

	void insert(int ver, int dis)
	{
		size++;
		heaps[size].dis = dis;
		heaps[size].ver = ver;
		hPos[ver] = size;

		pushUp(size);
	}

	bool verIsInHeap(int ver)
	{
		int rt = hPos[ver];
		return rt <= size;
	}

	bool isInHeap(int rt)
	{
		return rt <= size;
	}

	void extractMin()
	{
		swaphNode(1, size);
		--size;
		pushDown(1);
	}
};

int dijsktra(int src, int des, int vers)
{
	MinHeap mheap;
	for (int v = 1; v <= vers; v++)
	{
		mheap.insert(v, INT_MAX);
	}
	mheap.decrease(src, 0);

	for (int v = 1; v < vers; v++)
	{
		if (heaps[1].ver == des) return heaps[1].dis;
		int u = heaps[1].ver;
		int dis = heaps[1].dis;

		if (dis == INT_MAX) return INT_MAX;//防止溢出

		mheap.extractMin();

		int n = (int)gra[u].size();
		for (int j = 0; j < n; j++)
		{
			int ver = gra[u][j].des;
			int c = gra[u][j].cost;
			int rt = hPos[ver];

			if (mheap.isInHeap(rt) && dis+c < heaps[rt].dis)
			{
				mheap.decrease(ver, dis+c);
			}
		}
	}
	return heaps[1].dis;
}

int main()
{
	int T, n, p, nr, cost, r, src, des;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d", &n);
		memset(heaps, 0, sizeof(hNode) * (n+1));
		memset(hPos, 0, sizeof(int) * (n+1));
		for (int i = 0; i <= n; i++)
		{
			gra[i].clear();
		}

		map<string, int> msi;
		char str[MAX_C];
		for (int i = 1; i <= n; i++)
		{
			scanf("%s", str);
			msi[str] = i;
			scanf("%d", &p);
			for (int j = 0; j < p; j++)
			{
				scanf("%d %d", &nr, &cost);
				insertNeighbor(i, nr, cost);
			}
		}
		scanf("%d", &r);
		for (int i = 0; i < r; i++)
		{
			scanf("%s", str);
			src = msi[str];
			scanf("%s", str);
			des = msi[str];

			printf("%d\n", dijsktra(src, des, n));
		}
	}
	return 0;
}
时间: 2025-01-12 03:03:13

SPOJ 15. The Shortest Path 堆优化Dijsktra的相关文章

HDU4725 The Shortest Path in Nya Graph(堆优化的dijkstra算法)

题意: 这是一个非常容易解决的问题,您的任务只是计算图像,而仅是计算干草成本和算法成本.如果您不懂此段话,请继续.Nya图是具有“层”的无向图.图中的每个节点都属于一个层,总共有N个节点.您可以以成本C从x层中的任何节点移动到x + 1层中的任何节点,因为道路是双向的,因此也可以以相同的成本从x + 1层移动到x层.此外,还有M个额外的边,每个边连接一对节点u和v,成本为w.帮助我们计算从节点1到节点N的最短路径. 题解: 主要是建图. N个点,然后有N层,要假如2*N个点. 总共是3*N个点.

hdu1245+dij,堆优化

有一片100*100的湖泊,中心坐标(0,0),即湖泊右上角的坐标是(50,50),湖泊中间有一片以(0,0)为圆心,15为直径的圆形陆地.现有一个人在陆地,湖泊中散布着一些点可以踩,这个人要利用这些点跳到岸上,求最短路径和最短路径下的最短步数. spfa莫名其妙的超时,dij+堆优化反而能过...可能spfa更适合有向图吧. 使用vector<vector<node> > g这种双重结构时,最好先g.resize(N)设置一下容量,否则直接插入会出错. 1 #include<

【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost

[题目大意] 给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案. [思路] 在堆优化Dijkstra中,用pre记录前驱.如果新方案和旧方案相等,比较两个方案的字典序. [坑点] 我先求出了最短路(包括终点要付出代价),输出的时候再减去终点的代价. 有可能会给出S==T的情况--在这种情况下,最短路就是0,减去代价要变成负数了QAQ所以要特判一下.坑了好几个小时orz 1 #include<iostream> 2 #inclu

eoj1817 dijkstra单元最短路径 普通方法+二叉堆优化

求出有n(1 < n < 600)个结点有向图中,结点1到结点n的最短路径. Input 第一行有2个整数n和m(0 < m <= n*(n-1)/2),接下来m行每行有三个整数u,v,w结点u到v之间有一条权为w的边(w<1000000). Output 输出结点1到结点n之间的最短路径,如果1到n之间不存在路径,输出 -1. Sample Input 3 3 1 2 10 2 3 15 1 3 30 题目分析:dijkstra单元最短路径. 一.最短路径的最优子结构性质

dij+堆优化

写这个dij+堆优化的原因是有些地方卡SPFA,只能搞这个: 香甜的奶油: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<ctime> 7 #include<vector> 8 #include<algorithm> 9 #include&

bzoj3040 最短路+配对堆优化

3040: 最短路(road) Time Limit: 60 Sec  Memory Limit: 200 MBSubmit: 1859  Solved: 564[Submit][Status][Discuss] Description N个点,M条边的有向图,求点1到点N的最短路(保证存在).1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表示点数和边数.第二行六个整数T.rxa.rxc.rya.ryc.rp. 前T条边采用如下方式生成

Bzoj 2834: 回家的路 dijkstra,堆优化,分层图,最短路

2834: 回家的路 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 62  Solved: 38[Submit][Status][Discuss] Description Input Output Sample Input 2 1 1 2 1 1 2 2 Sample Output 5 HINT N<=20000,M<=100000 Source dijkstra+堆优化+分层图 把所有的横向和纵向分开看.跑最短路即可. 注意:N这么大,不能写

【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra

题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个城市登山,而是希望去另外什么地方喝下午茶.幸运的是,FGD的旅程不是既定的,他可以在某些旅行方案之间进行选择.由于FGD非常讨厌乘车的颠簸,他希望在满足他的要求的情况下,旅行的距离尽量短,这样他就有足够的精力来欣赏风景或者是泡MM了^_^.整个城市交通网络包含N个城市以及城市与城市之间的双向道路M条

dijkstra(迪杰斯特拉)最短路算法的堆优化

dijkstra(迪杰斯特拉)最短路算法是一种时间复杂度经过严格证明的最短路算法. 优化在于每次取最小值的时候采用堆优化,但是在最短路松弛过程中,dist是不断修改的,所以,为了能使复杂度降到O(nlogn),dist修改的同时,在堆中也要修改. 注意dijkstra(迪杰斯特拉)最短路算法只能用于正权边. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algo