UVA-10537 The Toll! Revisited (dijkstra)

题目大意:每经过一个地方就要交出相应的货物作为过路费,问将一批货物从起点运到终点,最少需要携带多少货物?

题目分析:在每一站交的过路费由当前拥有的货物量来决定,所以,要以终点为源点,求一次单源最短路即可。注意,输出要求路径字典序最小。

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;
# define LL long long

const LL INF=0x7fffffffffffffff;
struct Node
{
    int u;
    LL d;
    Node(int _u,LL _d):u(_u),d(_d){}
    bool operator < (const Node &a) const {
        return d>a.d;
    }
};
int vis[55],n,p,s,e,path[55];
LL dist[55];
vector<int>G[55];

LL get(LL d,int id)
{
    if(id>25)  return 1LL;
    LL l=d,r=d/(19LL)*(20LL)+19,ans;
    while(l<r){
        LL m=l+(r-l)/2;
        LL k=m-(m+(LL)19)/((LL)20);
        if(k>=d){
            r=m;
            ans=r;
        }else{
            l=m+1;
            ans=l;
        }
    }
    return ans-d;
    /*LL temp=d*20LL/19;
    while(temp-(temp+19LL)/20LL<d)   ++temp;
    return temp-d;*/
}

void dijkstra()
{
    for(int i=0;i<52;++i) path[i]=i;
    memset(vis,0,sizeof(vis));
    priority_queue<Node>q;
    fill(dist,dist+52,INF);
    dist[e]=p;
    q.push(Node(e,(LL)p));
    while(!q.empty())
    {
        Node u=q.top();
        q.pop();
        if(vis[u.u])    continue;
        vis[u.u]=1;
        for(int i=0;i<G[u.u].size();++i){
            int v=G[u.u][i];
            LL w=get(u.d,u.u);
            if(dist[v]>w+u.d){
                dist[v]=w+u.d;
                path[v]=u.u;
                q.push(Node(v,dist[v]));
            }else if(dist[v]==w+u.d&&path[v]>u.u){
                path[v]=u.u;
                q.push(Node(v,dist[v]));
            }
        }
    }
}

void print(int u)
{
    char c;
    if(u>25) c=u+'a'-26;
    else c=u+'A';
    if(path[u]==u){
        if(u!=s)
            printf("-");
        printf("%c
",c);
        return ;
    }
    if(u==s){
        printf("%c",c);
        print(path[u]);
    }else{
        printf("-%c",c);
        print(path[u]);
    }
}

int main()
{
    int u,v,cas=0;
    char a[2],b[2],S[2],E[2];
    while(scanf("%d",&n)&&n!=-1)
    {
        for(int i=0;i<52;++i) G[i].clear();
        for(int i=0;i<n;++i){
            scanf("%s%s",a,b);
            if(a[0]>='A'&&a[0]<='Z')    u=a[0]-'A';
            else    u=a[0]-'a'+26;
            if(b[0]>='A'&&b[0]<='Z')    v=b[0]-'A';
            else    v=b[0]-'a'+26;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        scanf("%d%s%s",&p,S,E);
        if(S[0]>='A'&&S[0]<='Z')    s=S[0]-'A';
        else    s=S[0]-'a'+26;
        if(E[0]>='A'&&E[0]<='Z')    e=E[0]-'A';
        else    e=E[0]-'a'+26;

        dijkstra();

        printf("Case %d:
",++cas);
        printf("%lld
",dist[s]);
        print(s);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/4908664.html