zoukankan      html  css  js  c++  java
  • 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
    ", dijsktra(src, des, n));
    		}
    	}
    	return 0;
    }




    版权声明:笔者靖心脏,景空间地址:http://blog.csdn.net/kenden23/,只有经过作者同意转载。

  • 相关阅读:
    Vue 消息无缝滚动
    请求不携带cookie问题
    vue中添加favicon
    自定义表单-校验数据规则
    vue 刷新当前页面的方式
    读阮一峰《ECMAScript 6 入门》小结
    Java进阶知识点3:更优雅地关闭资源
    Java进阶知识点2:看不懂的代码
    用Java实现异构数据库的高效通用分页查询功能
    Java进阶知识点1:白捡的扩展性
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4891002.html
Copyright © 2011-2022 走看看