逆向求最短路,递归输出路径。
思路上没什么难的。wa了半天没想到是数学公式推错了,最后也没想到可以一步推出来的公式。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
using namespace std;
typedef long long LL;
typedef unsigned long long LLU;
const LL INF=1e15;
const int maxn=60;
vector<int> G[maxn];
int m, st, en, g[maxn][maxn];
LL d[60];
int get_num(char c)
{
if(c>='A' && c<='Z')
return c-'A';
return c-'a'+26;
}
char get_char(int x)
{
if(x<26)
return x+'A';
return x-26+'a';
}
LL get_cost(int s, LL cost)
{
if(s>=26)return cost+1LL;
LL ans=(20LL*cost)/19LL;
while(ans-(ans+19)/20!=cost)
ans++;
return ans;
}
void init()
{
for(int i=0; i<maxn; i++)
G[i].clear();
memset(g, 0, sizeof(g));
}
void Add_Edge(int u, int v)
{
G[u].push_back(v);
g[u][v]=1;
}
void spfa(int s, LL c)
{
int vis[maxn]= {0};
for(int i=0; i<60; i++)
d[i]=INF;
d[s]=c;
vis[s]=1;
queue<int> q;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=0; i<G[u].size(); i++)
{
int v=G[u][i];
LL cost=get_cost(u, d[u]);
if(d[v]>cost)
{
d[v]=cost;
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
}
void print_road(int s, int e)
{
if(s==e)
cout<<get_char(s)<<endl;
for(int i=0; i<maxn; i++)
{
if(i>=26)
{
if(g[s][i] && d[s]-1LL==d[i])
{
cout<<get_char(s)<<"-";
print_road(i, e);
break;
}
}
else
{
if(g[s][i] && d[s]-(d[s]+19)/20==d[i])
{
cout<<get_char(s)<<"-";
print_road(i, e);
break;
}
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int kase=0;
while(cin>>m && m+1)
{
init();
for(int i=0; i<m; i++)
{
char a, b;
cin>>a>>b;
Add_Edge(get_num(b), get_num(a));
Add_Edge(get_num(a), get_num(b));
}
char s, e;
LL cost;
cin>>cost>>s>>e;
st=get_num(s);
en=get_num(e);
spfa(get_num(e), cost);
cout<<"Case "<<++kase<<":"<<endl<<d[st]<<endl;
print_road(st, en);
}
return 0;
}