UVa - 10537 - The Toll! Revisited(单源最短路)

逆向求最短路,递归输出路径。

思路上没什么难的。wa了半天没想到是数学公式推错了,最后也没想到可以一步推出来的公式。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
using namespace std;
typedef long long LL;
typedef unsigned long long LLU;
const LL INF=1e15;
const int maxn=60;

vector<int> G[maxn];
int m, st, en, g[maxn][maxn];
LL d[60];

int get_num(char c)
{
    if(c>='A' && c<='Z')
        return c-'A';
    return c-'a'+26;
}

char get_char(int x)
{
    if(x<26)
        return x+'A';
    return x-26+'a';
}

LL get_cost(int s, LL cost)
{
    if(s>=26)return cost+1LL;
    LL ans=(20LL*cost)/19LL;
    while(ans-(ans+19)/20!=cost)
        ans++;
    return ans;
}

void init()
{
    for(int i=0; i<maxn; i++)
        G[i].clear();
    memset(g, 0, sizeof(g));
}

void Add_Edge(int u, int v)
{
    G[u].push_back(v);
    g[u][v]=1;
}

void spfa(int s, LL c)
{
    int vis[maxn]= {0};
    for(int i=0; i<60; i++)
        d[i]=INF;

    d[s]=c;
    vis[s]=1;
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=0; i<G[u].size(); i++)
        {
            int v=G[u][i];
            LL cost=get_cost(u, d[u]);
            if(d[v]>cost)
            {
                d[v]=cost;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}

void print_road(int s, int e)
{
    if(s==e)
        cout<<get_char(s)<<endl;
    for(int i=0; i<maxn; i++)
    {
        if(i>=26)
        {
            if(g[s][i] && d[s]-1LL==d[i])
            {
                cout<<get_char(s)<<"-";
                print_road(i, e);
                break;
            }
        }
        else
        {
            if(g[s][i] && d[s]-(d[s]+19)/20==d[i])
            {
                cout<<get_char(s)<<"-";
                print_road(i, e);
                break;
            }
        }

    }
}

int main()
{
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int kase=0;
    while(cin>>m && m+1)
    {
        init();
        for(int i=0; i<m; i++)
        {
            char a, b;
            cin>>a>>b;
            Add_Edge(get_num(b), get_num(a));
            Add_Edge(get_num(a), get_num(b));
        }
        char s, e;
        LL cost;
        cin>>cost>>s>>e;
        st=get_num(s);
        en=get_num(e);
        spfa(get_num(e), cost);
        cout<<"Case "<<++kase<<":"<<endl<<d[st]<<endl;
        print_road(st, en);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值