题目链接
题意:给定一个无向图,大写字母是城市,小写字母是村庄,经过城市交过路费为当前货物的%5,路过村庄固定交1,给定起点终点和到目标地点要剩下的货物,问最少要带多少货物上路,并输出路径,如果有多种方案,要求字典序最小
solution:反向建图, d[i]表示从i到终点需要的数量。
#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 105;
const long long Inf = (1LL<<61);
struct Edge{int u, v, w;Edge(int u, int v, int w):u(u),v(v),w(w){}
};
struct HeapNode{long long d;int u;bool operator<(const HeapNode& rhs) const{return d>rhs.d;}
};char to[255];struct Dijkstra{int n, m;long long d[N];bool done[N];vector<Edge> edges;vector<int> G[N];int p[N];void init(int n){this->n=n;for ( int i=0; i<n; i++ ) G[i].clear();edges.clear(); }void addeage(int u, int v, int w){edges.push_back((Edge){u,v,w});m=edges.size();G[u].push_back(m-1);}void print(int u){if( p[u]==-1 ){printf("%c\n", to[u]);return;}printf("%c-", to[u] );print(edges[p[u]].u);}void dijkstra(int s, long long vl){for ( int i=0; i<n; i++ ) d[i]=Inf, done[i]=0;d[s]=vl;p[s]=-1;priority_queue<HeapNode> Q;Q.push((HeapNode){vl,s});while( !Q.empty() ){HeapNode x=Q.top(); Q.pop();int u=x.u;if( done[u] ) continue;done[u]=1;for ( int i=0; i<G[u].size(); i++ ){Edge& e=edges[G[u][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[edges[p[e.v]].u] ){d[e.v]=nd;p[e.v]=G[u][i];Q.push((HeapNode){d[e.v],e.v});}}}}
};struct SPFA{int n, m;long long d[N];bool inq[N];int p[N];vector<Edge> edges;vector<int> G[N];void init(int n){this->n=n;for ( int i=0; i<n; i++ ) G[i].clear();edges.clear();}void addeage(int u, int v, int w){edges.push_back((Edge){u,v,w});m=edges.size();G[u].push_back(m-1);}void print(int u){if( p[u]==-1 ){printf("%c\n", to[u] );return ;}printf("%c-", to[u] );print(edges[p[u]].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=0; i<G[u].size(); i++ ){Edge& e=edges[G[u][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[edges[p[e.v]].u] ){d[e.v]=nd;p[e.v]=G[u][i];if( !inq[e.v] ){inq[e.v]=1;Q.push(e.v);}}}}}
};
SPFA D;
int vis[255];
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 ){D.init(52);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]];D.addeage(u,v,a[0]<'a');D.addeage(v,u,b[0]<'a');}long long vl;scanf("%lld%s%s", &vl, a, b );int u=vis[a[0]], v=vis[b[0]];D.spfa(v,vl);printf("Case %d:\n", ++kas); printf("%lld\n", D.d[u]); D.print(u);}
}