LA 5854 Long Distance Taxi (SPFA 变型) - from lanshui_Yang

来源:互联网 发布:瓜子二手车网站源码 编辑:程序博客网 时间:2024/05/16 07:58

      题目大意:直接抽象一下,有多个城市,这些城市之间有n条无向边,有一个旅行家(假设叫Mike),他有一辆摩托车,摩托车的邮箱大小为cap,其耗油量是 10千米/每升油,给定一个起点、一个终点和cap的值以及有加油站的城市 (Mike 可以在这些城市加满油),让你判断Mike是否可以从起点到达终点,如果可以,就求出路程的最小值,否则,就输出"-1"。

      解题思路:这道题是一道变型的最短路问题,比普通的最短路难了许多。一般的最短路问题可以用SPFA解决,这道题也可以,但有些变化,这里队列中的对象是二维的,一个是顶点的编号,一个是摩托车还能走的路程。

      请看代码:

#include<iostream>#include<cstring>#include<string>#include<cmath>#include<cstdio>#include<vector>#include<set>#include<queue>#include<map>#include<algorithm>#define mem(a , b ) memset(a , b , sizeof(a))using namespace std ;const int MAXN = 3006 ;const int INF = 0x7fffffff ;struct Edge{    int adj ;    int d ;    int next ;}E[MAXN * 2] ;int head[MAXN * 2] ;int ed ;struct Q{    int Node ;    int C ;};int n , m , cap ;string s1 , s2 ;int st , e ;map<string , int> mp ;int cnt ;bool inq[MAXN * 2][2006] ;int dis[MAXN * 2][2006] ;bool P[MAXN * 2] ; // 判断城市是否有加油站char ss1[100] , ss2[100] ;void chu(){    mp.clear() ;    cnt = 0 ;    ed = 0 ;    mem(head , 0) ;    mem(dis , 0) ;    mem(P , 0) ;    mem(inq , 0) ;}void init(){    chu() ;    scanf("%s%s" , ss1 , ss2) ;    s1 = string(ss1) ;    s2 = string(ss2) ;    if(mp.find(s1) == mp.end())    {        mp[s1] = ++ cnt ;    }    if(mp.find(s2) == mp.end())    {        mp[s2] = ++ cnt ;    }    st = mp[s1] ;    e = mp[s2] ;    cap *= 10 ;    int i ;    int td ;    int ta , tb ;    for(i = 0 ; i < n ; i ++)    {        scanf("%s%s" , ss1 , ss2) ;        s1 = string(ss1) ;        s2 = string(ss2) ;        scanf("%d" , &td) ;        if(!mp[s1])        {            mp[s1] = ++ cnt ;        }        if(!mp[s2])        {            mp[s2] = ++ cnt ;        }        ta = mp[s1] ;        tb = mp[s2] ;        if(td <= cap)  // 建图        {            ++ ed ;            E[ed].adj = tb ;            E[ed].d = td ;            E[ed].next = head[ta] ;            head[ta] = ed ;            ++ ed ;            E[ed].adj = ta ;            E[ed].d = td ;            E[ed].next = head[tb] ;            head[tb] = ed ;        }    }    for(i = 0 ; i < m ; i ++)    {        scanf("%s" , ss1) ;        s1 = string(ss1) ;        if(!mp[s1])        {            mp[s1] = ++ cnt ;        }        int t = mp[s1] ;        P[t] = true ;    }}queue<Q> q ;void spfa(Q u){    while (!q.empty()) q.pop() ;    q.push(u) ;    inq[u.Node][u.C] = true ;    while (!q.empty())    {        Q v = q.front() ;        q.pop() ;        inq[v.Node][v.C] = false ;        int i ;        i = head[v.Node] ;        while (i != 0)        {            Edge tv = E[i] ;            int vn = tv.adj ;            int vd = tv.d ;            int se = v.C - vd ;            if(P[vn]) // 注意此处            {                se = cap ;            }            if(v.C - vd >= 0 && dis[v.Node][v.C] + vd < dis[vn][se] )            {                dis[vn][se] = dis[v.Node][v.C] + vd  ;                if(!inq[vn][se])                {                    inq[vn][se] = true ;                    Q tmp ;                    tmp.Node = vn ;                    tmp.C = se ;                    q.push(tmp) ;                }            }            i = E[i].next ;        }    }}void solve(){    int i , j ;    for(i = 1 ; i <= cnt ; i ++)    {        for(j = 0 ; j <= cap ; j ++)            dis[i][j] = INF ;    }    dis[st][cap] = 0 ;    Q Stmp ;    Stmp.Node = st ;    Stmp.C = cap ;    spfa(Stmp) ;    int MIN = INF ;    for(i = 0 ; i <= cap ; i ++)    {        MIN = min(MIN , dis[e][i]) ;    }    if(MIN == INF)        puts("-1") ;    else        printf("%d\n" , MIN) ;}int main(){    while (scanf("%d%d%d" , &n , &m , &cap) != EOF)    {        if(n == 0 && m == 0 && cap == 0)            break ;        init() ;        solve() ;    }    return 0 ;}




原创粉丝点击