uva10537

题目大意

                 第一行给出N说明有N条路;

                  接下来n行字母对(a,b)大写表示城镇小写表示村庄村庄税收为1,城镇税收为1/20向上取整;

                   然后是一个数字和初始城镇目的城镇;求出耗费最小的路径并打出字典序最小的

倒着求

#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<string>
#include<queue>
#include<utility>

using namespace std;

typedef long long LL;

#define MAXN 210
const LL INF=1LL<<60;

vector<int> g[200];

int k,m,vis[MAXN];
LL h[MAXN];

void add(int u,int v)
{
    g[u].push_back(v);
    g[v].push_back(u);
}

LL maintain(char u ,LL x)
{
    if(isupper(u)) return x-(x+19)/20;
    return x-1;
}

LL cost(char u)
{
    if(islower(u)) return h[u]+1;
    LL tmp=h[u]*20/19;
    while(maintain(u,tmp)<h[u]) tmp++;
    return tmp;
}

void dijkstra(int s,int ed)
{

    int i,j,u;
    for(int i=1; i<=200; i++)
        h[i]=INF,vis[i]=0;
    h[s]=k,vis[s]=1;
    for(int i=0; i<g[s].size(); i++)
        h[g[s][i]]=cost(s);
    for(i=1; i<=200; i++)
    {
        if(vis[ed]) break;
        LL min=INF;
        for(j=1; j<=200; j++)
            if(!vis[j] && h[j]<=min)
            {
                u=j;
                min=h[j];
            }
        if(min==INF) break;
        vis[u]=1;
        for(int j=0; j<g[u].size(); j++)
        {
            int v=g[u][j];
            if(!vis[v]&&h[v]>=cost(u)) h[v]=cost(u);
        }
    }
}
int main()
{
    int cs=1;
    while(~scanf("%d",&m)&&m!=-1)
    {
        char u[6],v[6];
        for(int i='A'; i<='Z'; i++)
            g[i].clear();
        for(int i='a'; i<='z'; i++)
            g[i].clear();
        for(int i=0; i<m; i++)
        {
            scanf("%s%s",u,v);
            add(u[0],v[0]);
        }
        for(int i='A'; i<='Z'; i++)
            sort(g[i].begin(),g[i].end());
        for(int i='a'; i<='z'; i++)
            sort(g[i].begin(),g[i].end());
        scanf("%d%s%s",&k,u,v);
        dijkstra(v[0],u[0]);
        printf("Case %d:\n",cs++);
        printf("%lld\n",h[u[0]]);
        printf("%c",u[0]);
        char pre=u[0];
        while(pre!=v[0])
        {
            for(int i=0; i<g[pre].size(); i++)
            {
                char to=g[pre][i];
                if(maintain(to,h[pre])==h[to] )
                {
                    pre=to;
                    break;
                }
            }

            printf("-%c",pre);
        }
        printf("\n");
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值