The Toll! Revisited UVA

给定图G=VEG=(V,E),VV中有两类点,一类点(AA类)在进入时要缴纳1的费用,另一类点(BB类)在进入时要缴纳当前携带金额的1/20(不足20的部分按20算) 
已知起点为SS,终点为TT,希望在到达TT时能够拥有PP的金额,问一开始在SS最少要携带多少金额,并求出路径(若有多条,输出字典序最小的) 
SS离开时不需要缴费,进入TT时需要缴费

倒序找最短路  d[i] 表示从i到终点需要的最少的金额 在更新d的时候 分两种情况 

#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10500;
const long long Inf = (1LL<<61);
int head[N];
int vis[255];
int cnt;
char to[255];
int n, m;
long long d[N];
bool inq[N];
int p[N];
struct Edge{
    int v, w, next;
}edges[N*5];

void add(int u ,int v, int w)
{
    edges[cnt].v = v;
    edges[cnt].w = w;
    edges[cnt].next = head[u];
    head[u] = cnt++;
}

void init()
{
    memset(head, -1, sizeof(head));
    cnt = 0;
}

void print(int u){
    if( p[u]==-1 ){
        printf("%c
", to[u] );
        return ;
    }
    printf("%c-", to[u] );
    print(p[u]);
}
void spfa(int s, long long vl){
    for ( int i=0; i<N; i++ ) d[i]=Inf, inq[i]=0;
    d[s]=vl;
    p[s]=-1;
    queue<int> Q;
    Q.push(s);
    while( !Q.empty() ){
        int u=Q.front(); Q.pop();
        inq[u]=0;
        for ( int i=head[u]; i!=-1; i=edges[i].next ){
            Edge e=edges[i];
            long long nd;
            if(e.w) nd=(long long) ceil(d[u]*1.0/19*20);  //推一下公式。。虽然我没推出来
            else nd=d[u]+1;
            if( d[e.v]>nd || d[e.v]==nd && to[u]<to[p[e.v]] ){  //如果相等 则判断字典序
                d[e.v]=nd;
                p[e.v]=u;
                if( !inq[e.v] ){
                    inq[e.v]=1;
                    Q.push(e.v);
                }
            }
        }
    }
}

int main(){
    for ( int i=0; i<26; i++ ) {
        vis['a'+i]=i+26; to[i+26]='a'+i;
        vis['A'+i]=i; to[i]='A'+i;
    }
    int n, m, kas=0;
    while( scanf("%d", &m ) == 1 && m!=-1 ){
        init();
        char a[2], b[2];
        for ( int i=1; i<=m; i++ ){
            scanf("%s%s", a, b );
            int u=vis[a[0]], v=vis[b[0]];
            add(u,v,a[0]<'a');
            add(v,u,b[0]<'a');
        }
        long long vl;
        scanf("%lld%s%s", &vl, a, b );
        int u=vis[a[0]], v=vis[b[0]];
        spfa(v,vl);
        printf("Case %d:
", ++kas);
        printf("%lld
", d[u]);
        print(u);
    }
}
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
原文地址:https://www.cnblogs.com/WTSRUVF/p/9407654.html