从终点到起点倒推一遍最短路,此外我用了一个特殊的cost函数来根据当前载货量来动态的计算每条边的权重。
另一个卡点是在最短路的前提下,按字典序输出路径。 可以在“松弛”操作上做点小文章,即当 “新dist与旧dist值相等” 并且 “新的当前节点编号<旧的当前节点编号” 时更新存储着父节点的fa数组。
#include <stack>
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <cctype>
using namespace std;
typedef long long ll;
const ll BIG=1;
const ll SMALL=0;
const ll inf=0x3f3f3f3f3f3f3f;
const ll maxn=125+10;
ll getcost(ll d,ll t){
if(t==BIG){
ll x=d/19;
if(d%19>0) x++;
return x;
}
else return 1;
}
struct qnode{
ll v;
ll c;
qnode(ll _v=0,ll _c=0):v(_v),c(_c){}
bool operator <(const qnode &r)const{
return c>r.c;
}
};
struct Edge{
ll v,t;
Edge(ll _v=0,ll _cost=0):v(_v),t(_cost){}
};
vector<Edge> e[maxn];
bool vis[maxn];
ll dist[maxn];
char fa[maxn];
void dijkstra(ll n,ll start,ll initvalue){
memset(vis,false,sizeof(vis));
//memset(dist,inf,sizeof(dist));
for(ll i=0;i<maxn;i++) dist[i]=inf;
priority_queue<qnode> q;
dist[start]=initvalue;
q.push(qnode(start,0));
qnode tmp;
while(!q.empty()){
tmp=q.top();
q.pop();
ll u=tmp.v;
if(vis[u]) continue;
vis[u]=true;
for(ll i=0;i<e[u].size();i++){
ll v=e[u][i].v;
ll cost=getcost(dist[u],e[u][i].t);
if(!vis[v]){
if((dist[v]>dist[u]+cost)||((dist[v]==dist[u]+cost)&&fa[v]>u)){
fa[v]=u;
dist[v]=dist[u]+cost;
q.push(qnode(v,dist[v]));
}
}
}
}
}
int main(){
ll t=0;
ll m,good;
char u,v,source,target;
while(~scanf("%lld",&m)&&m!=-1){
for(ll i=0;i<maxn;i++) e[i].clear();
for(ll i=0;i<m;i++){
scanf("\n%c %c",&u,&v);
if(u==v) continue;
if(isupper(v)) e[v].push_back(Edge(u,BIG));
else e[v].push_back(Edge(u,SMALL));
if(isupper(u)) e[u].push_back(Edge(v,BIG));
else e[u].push_back(Edge(v,SMALL));
}
scanf("%lld %c %c",&good,&target,&source);
dijkstra(128,source,good);
printf("Case %lld:\n",++t);
printf("%lld\n",dist[target]);
char x=target;
while(x!=source){
printf("%c-",x);
x=fa[x];
}
printf("%c\n",source);
}
return 0;
}