spoj_15_SHPATH

题目数据范围比较高,用map记录城市,再用dijkstra+heap既可以了AC了

/*
 *NAME:SHPATH
 *LANG:C++
 *Source:spoj15
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <string>
#include <map>
#define INF 0x7FFFFFFF
using namespace std;

int n,m,s,hl,start,end,k;
string name,startStr,endStr;
map<string,int> city;//用来储存名称于城市编号的对应关系
struct heapNode{
    int v,d;
}heap[10101];
struct node{
    int v,w;
    node *next;
};
node *g[10101];
int hpos[10101];

inline void insert(int a,int b,int w){
    node *x= new node;
    x->v=b;x->w=w;x->next=g[a];g[a]=x;
}
inline void init(){
    city.clear();
    memset(hpos,0,sizeof(hpos));
    memset(g,0,sizeof(g));
    memset(heap,0,sizeof(heap));
    for (int i=1;i<=n;++i){
	cin >> name;
	city[name]=i;
	cin >> m;
	for (int j=1;j<=m;++j){
	    int x,y;
	    cin >> x >> y;
	    insert(i,x,y);
	}
    }
}
inline void swap(int x,int y){
    heap[0]=heap[x];heap[x]=heap[y];heap[y]=heap[0];
    hpos[heap[x].v]=x;hpos[heap[y].v]=y;
}
inline void heapUp(int i){
    while (i!=1 && heap[i].d<heap[i/2].d){
	swap(i,i/2);
	i/=2;
    }
}
inline void heapDown(){
    int i=2;
    while (i<=hl){
	if (i<hl && heap[i].d>heap[i+1].d) ++i;
	if (heap[i].d<heap[i/2].d){
	    swap(i,i/2);
	    i*=2;
	}
	else
	    break;
    }
}
inline void relax(int u,int v,int w){
    if (heap[hpos[u]].d+w<heap[hpos[v]].d){
	heap[hpos[v]].d=heap[hpos[u]].d+w;
	heapUp(hpos[v]);
    }
}
inline void dijkstra(){
    int u;node *p = 0;
    for (int u=1;u<=n;++u){
	heap[u].v=u;
	heap[u].d=INF;
	hpos[u]=u;
    }
    heap[start].d=0;swap(1,start);
    hl=n;
    while (hl>0){
	u=heap[1].v;
	swap(1,hl);hl--;heapDown();
	p=g[u];
	while (p!=0){
	    if (hpos[p->v]<=hl) relax(u,p->v,p->w);
	    p=p->next;
	}
    }
}
inline void print(){
    cout << heap[hpos[end]].d << endl;
}
int main(){
    std::ios::sync_with_stdio(false);
    cin >> s;
    while (s--){
	cin >> n;
	init();
	cin >> k;
	for (int i=1;i<=k;++i){
	    cin >> startStr >> endStr;
	    start=city[startStr];end=city[endStr];
	    dijkstra();
	    print();
	}
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值