zoukankan      html  css  js  c++  java
  • SPOJ 15. The Shortest Path 最短路径题解

    本题就是给出一组cities。然后以下会询问,两个cities之间的最短路径。

    属于反复询问的问题,临时我仅仅想到使用Dijsktra+heap实现了。

    由于本题反复查询次数也不多,故此假设保存全部最短路径,那么是得不偿失了。

    所以还是反复使用Dijsktra吧。

    有没有更加好的办法处理反复查询问题呢?还没想到。

    本算法纯粹手工打造了,不使用stl。代码非常长非常长,光打一遍就会手软的,呵呵。

    原题:

    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

    #pragma once
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <string>
    #include <map>
    using namespace std;
    
    class TheShortestPath15
    {
    	struct Node
    	{
    		int des, weight;
    		Node *next;
    		Node(int d, int w) : des(d), weight(w), next(NULL) {}
    	};
    
    	struct AdjList
    	{
    		Node *head;
    		AdjList() : head(NULL) {}
    	};
    
    	struct Graph
    	{
    		int v;
    		AdjList *arr;
    		Graph(int v1) : v(v1)
    		{
    			arr = new AdjList[v];
    		}
    		~Graph()
    		{
    			for (int i = 0; i < v; i++)
    			{
    				Node *h = arr[i].head;
    				while (h)
    				{
    					Node *next = h->next;
    					delete h, h = NULL;
    					h = next;
    				}
    			}
    			delete arr, arr = NULL;
    		}
    	};
    
    	void addEdge(Graph *gra, int src, int des, int w)
    	{
    		Node *n = new Node(des, w);
    		n->next = gra->arr[src].head;
    		gra->arr[src].head = n;
    		/*
    		n = new Node(src, w);
    		n->next = gra->arr[des].head;
    		gra->arr[des].head = n;
    		*/
    	}
    
    	struct HeapNode
    	{
    		int v, dist;
    		explicit HeapNode(int v1, int d) : v(v1), dist(d) {}
    	};
    
    	struct Heap
    	{
    		int size, cap;
    		int *pos;
    		HeapNode **arr;
    		Heap(int c) : cap(c), size(0)
    		{
    			pos = new int[c];
    			arr = new HeapNode*[c];
    		}
    		~Heap()
    		{
    			delete [] pos, pos = NULL;
    			for (int i = 0; i < size; i++)
    			{
    				if (arr[i]) delete arr[i], arr[i] = NULL;
    			}
    			delete [] arr;
    		}
    	};
    
    	void swapHeapNodes(HeapNode **a, HeapNode **b)
    	{
    		HeapNode *c = *a;
    		*a = *b;
    		*b = c;
    	}
    
    	void heapify(Heap *heap, int node)
    	{
    		if (!heap) return ;
    		int minN = node;
    		int left = (node<<1) + 1;
    		int right = (node<<1) + 2;
    
    		if (left < heap->size &&
    			heap->arr[left]->dist < heap->arr[minN]->dist) minN = left;
    		
    		if (right < heap->size &&
    			heap->arr[right]->dist < heap->arr[minN]->dist) minN = right;
    
    		if (minN != node)
    		{
    			heap->pos[heap->arr[minN]->v] = node;
    			heap->pos[heap->arr[node]->v] = minN;
    
    			swapHeapNodes(&heap->arr[minN], &heap->arr[node]);
    
    			heapify(heap, minN);
    		}
    	}
    
    	inline bool isEmpty(Heap *heap)
    	{
    		return heap->size == 0;
    	}
    
    	HeapNode *extraMin(Heap *heap)
    	{
    		if (isEmpty(heap)) return NULL;
    
    		HeapNode *root = heap->arr[0];
    		HeapNode *last = heap->arr[heap->size-1];
    		heap->arr[0] = last;//别漏了这步。

    heap->pos[root->v] = heap->size-1; heap->pos[last->v] = 0; --heap->size; //别忘记先-- heapify(heap, 0); return root; } void decreaseKey(Heap *heap, int v, int dist) { int i = heap->pos[v]; heap->arr[i]->dist = dist; while (i && heap->arr[i]->dist < heap->arr[(i-1)>>1]->dist) { heap->pos[heap->arr[i]->v] = (i-1)>>1; heap->pos[heap->arr[(i-1)>>1]->v] = i; swapHeapNodes(&heap->arr[i], &heap->arr[(i-1)>>1]); i = (i-1)>>1; } } inline bool isInHeap(Heap *heap, int v) { return heap->pos[v] < heap->size; } void dijsktra(Graph *gra, int src, int des, int dist[]) { Heap *heap = new Heap(gra->v); heap->size = gra->v; for (int i = 0; i < gra->v; i++) { dist[i] = INT_MAX; heap->pos[i] = i; heap->arr[i] = new HeapNode(i, dist[i]); } dist[src] = 0; decreaseKey(heap, src, 0); while (!isEmpty(heap)) { HeapNode *hn = extraMin(heap); int u = hn->v; delete hn, hn = NULL; if (u == des) break; //这里添加代码。仅仅找到目标节点就可返回了 if (dist[u] == INT_MAX) break; Node *n = gra->arr[u].head; while (n) { if (isInHeap(heap, n->des) && n->weight + dist[u] < dist[n->des]) { dist[n->des] = n->weight + dist[u]; decreaseKey(heap, n->des, dist[n->des]); } n = n->next; } } delete heap; } public: TheShortestPath15() { int s, n, p, nr, cost, r; map<string, int> cities; string name; scanf("%d", &s); while (s--) { scanf("%d", &n); Graph *gra = new Graph(n); for (int i = 0; i < n; i++) { //gets(NAME);教训:gets是取到 或者EOF结束的,不是取单个单词 cin>>name; cities[name] = i; scanf("%d", &p); while (p--) { scanf("%d %d", &nr, &cost); addEdge(gra, i, nr-1, cost); } } scanf("%d", &r); while (r--) { cin>>name; int src = cities[name]; cin>>name; int des = cities[name]; int *dist = (int *) malloc(sizeof(int) * n); dijsktra(gra, src, des, dist); printf("%d ", dist[des]); if (dist) free(dist); } delete gra; } } };




  • 相关阅读:
    springboot嵌入式servlet容器的自动配置以及原理
    简单认识springboot的错误处理机制
    使用springboot来编写web项目的一些实现
    spring-cloud-starter-openfeign 源码详细讲解
    简述application.properties和application.yml 以及 @ConfigurationProperties 和@PropertySource @Value 和@ImportResource的用法,区别
    Ribbon源码分析(二)-- 服务列表的获取和负载均衡算法分析
    git的详细使用,项目创建到同步远程仓库,版本回退,忽略文件,分支创建,分支合并,分支名称修改,冲突解决,项目迁移
    Ribbon源码分析(一)-- RestTemplate 以及自定义负载均衡算法
    eureka源码--服务的注册、服务续约、服务发现、服务下线、服务剔除、定时任务以及自定义注册中心的思路
    eureka集群的搭建
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/7146321.html
Copyright © 2011-2022 走看看