因为迪杰斯特拉要考虑的关键字太多,并且还有一个关键字为路径长度,不好写。可以尝试以下搜索,当然这是因为这题的数据量并不大。
比较简单,详情看注释
#include<iostream>
#include<vector>
#include<stack>
#include<algorithm>
#include<queue>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,ll> PII;
const int N=205;
const ll inf=1e18;
//cnt为最短路径的条数,题目保证存在这样的路径,所以cnt最小值为1
int n,m,cnt=1;
//邻接表存图,g[i].first表示i到first存在一条值为g[i].second路径
vector<PII> g[N];
//vis表示该点是否被访问过
bool vis[N];
//存每个点的敌人数量
ll v[N];
//将城市名映射为数字
unordered_map<string,int> mp;
//将数字映射为城市名
string name[N];
//城市名对应的编号
int idx;
//起点和终点的城市名
string st,ed;
//起点和终点对应的编号
int id1,id2;
//path存储当前搜索的路径,res为最终路径
vector<int> res,path;
//cnt1是路径长度,cnt2杀敌数量
ll cnt1=inf,cnt2;
//在搜索过程中,储存对应cnt1,cnt2两个变量
ll tmp1,tmp2;
void dfs(int u)
{
if(u==id2)//达到终点
{
if(tmp1<=cnt1)//路径的长度小于答案的长度
{
//统计最短路径条数,若有比答案还小的则置为1(当前的路径为1)
if(tmp1==cnt1)
++cnt;
else
cnt=1;
//路径长度一样比较经过点的个数
if(tmp1==cnt1&&res.size()>path.size())
return;
//经过点的个数相同比较杀敌数量
if(tmp1==cnt1&&res.size()==path.size()&&cnt2>tmp2)
return;
//比答案更优,更新答案
cnt1=tmp1;
cnt2=tmp2;
res=path;
}
return ;
}
//搜索过程
for(int i=0;i<g[u].size();++i)
{
int to=g[u][i].first;
if(vis[to])
continue;
vis[to]=1;
tmp1+=g[u][i].second;
tmp2+=v[to];
path.push_back(to);
dfs(to);
vis[to]=0;
tmp1-=g[u][i].second;
tmp2-=v[to];
path.pop_back();
}
return ;
}
int main()
{
cin>>n>>m>>st>>ed;
mp[st]=++idx;
name[idx]=st;
mp[ed]=++idx;
name[idx]=ed;
id1=mp[st];
id2=mp[ed];
for(int i=1;i<=n-1;++i)
{
string tmp;
ll t;
cin>>tmp>>t;
//cout<<tmp<<'\n';
if(mp.count(tmp)==0)
mp[tmp]=++idx;
v[mp[tmp]]=t;
name[mp[tmp]]=tmp;
}
while(m--)
{
string x,y;
cin>>x>>y;
ll w;
scanf("%lld",&w);
g[mp[x]].push_back({mp[y],w});
g[mp[y]].push_back({mp[x],w});
}
vis[id1]=1;
dfs(id1);
cout<<st<<"->";
for(int i=0;i<res.size();++i)
{
cout<<name[res[i]];
if(i!=res.size()-1)
cout<<"->";
}
puts("");
cout<<cnt<<" ";
cout<<cnt1<<' '<<cnt2<<'\n';
return 0;
}
/*
4 4 a c
b 10
c 10
d 0
a b 1
b c 2
b d 1
d c 1
*/