The Toll! Revisited UVA - 10537(变形。。)

时间:2023-03-08 18:29:11

给定图G=(V,E)G=(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 = ;
const long long Inf = (1LL<<);
int head[N];
int vis[];
int cnt;
char to[];
int n, m;
long long d[N];
bool inq[N];
int p[N];
struct Edge{
int v, w, next;
}edges[N*]; 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, -, sizeof(head));
cnt = ;
} void print(int u){
if( p[u]==- ){
printf("%c\n", to[u] );
return ;
}
printf("%c-", to[u] );
print(p[u]);
}
void spfa(int s, long long vl){
for ( int i=; i<N; i++ ) d[i]=Inf, inq[i]=;
d[s]=vl;
p[s]=-;
queue<int> Q;
Q.push(s);
while( !Q.empty() ){
int u=Q.front(); Q.pop();
inq[u]=;
for ( int i=head[u]; i!=-; i=edges[i].next ){
Edge e=edges[i];
long long nd;
if(e.w) nd=(long long) ceil(d[u]*1.0/*); //推一下公式。。虽然我没推出来
else nd=d[u]+;
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]=;
Q.push(e.v);
}
}
}
}
} int main(){
for ( int i=; i<; i++ ) {
vis['a'+i]=i+; to[i+]='a'+i;
vis['A'+i]=i; to[i]='A'+i;
}
int n, m, kas=;
while( scanf("%d", &m ) == && m!=- ){
init();
char a[], b[];
for ( int i=; i<=m; i++ ){
scanf("%s%s", a, b );
int u=vis[a[]], v=vis[b[]];
add(u,v,a[]<'a');
add(v,u,b[]<'a');
}
long long vl;
scanf("%lld%s%s", &vl, a, b );
int u=vis[a[]], v=vis[b[]];
spfa(v,vl);
printf("Case %d:\n", ++kas);
printf("%lld\n", d[u]);
print(u);
}
}