The Toll! Revisited UVA - 10537(变形。。)
给定图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 = 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\n", 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:\n", ++kas); printf("%lld\n", d[u]); print(u); } }
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。