
![]()

代码一、常规算法,比较麻烦
//使用map容器将字符串和数字建立关系
//dijkstra算法保存路径
#include<iostream>
#include<vector>
#include<map>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 210;
map<string,int>mp;
int n,k,w;
struct edge
{
int to,cost;
};
vector<edge> G[N];
int num[N]; //每个城镇敌军数量
int dis[N]; //最短距离
int cnt[N]; //解放城镇数量
int sumnum[N]; //能杀伤多少敌军
int pred[N]; //记录上一个节点序号
int cntshort[N]; //到某个顶点的最短路条数
int book[N]; //记录是否访问过
vector<int>ljd;
int s,des;
void dijkstra()
{
for(int i=0;i<n;i++)
dis[i]=INF;
dis[s]=0;
cntshort[s]=1; //到某个顶点的最短路条数
book[s]=1;
for(int i=0;i<G[s].size();i++) //对起点的邻接点进行初始化
{
int next=G[s][i].to;
dis[next]=G[s][i].cost; //距离
cntshort[next]=1; //最短路径条数
sumnum[next]=num[next]; //杀敌数量
pred[next]=s; //前一个节点
}
int Min,Minnum;
for(int i=1;i<n;i++)
{
Min=INF+1;
Minnum=-1;
for(int j=1;j<n;j++)
{
if(dis[j]<Min&&book[j]!=1)
{
Min=dis[j];
Minnum=j;
}
}
book[Minnum]=1;
for(int j=0;j<G[Minnum].size();j++)
{
edge& e=G[Minnum][j];
int d2=dis[Minnum]+e.cost; //待更新的距离
if(dis[e.to]>d2)
{
dis[e.to]=d2;
pred[e.to]=Minnum;
cnt[e.to]=cnt[Minnum]+1; //解放城市数量加1
sumnum[e.to]=sumnum[Minnum]+num[e.to]; //杀死军队数量
cntshort[e.to]=cntshort[Minnum]; //最短路条数
}
else if(dis[e.to]==d2)
{
cntshort[e.to]+=cntshort[Minnum]; //最短路径条数
//解放城市
if(cnt[e.to]<cnt[Minnum]+1)
{
pred[e.to]=Minnum;
cnt[e.to]=cnt[Minnum]+1;
sumnum[e.to]=sumnum[Minnum]+num[e.to];
}
else if(cnt[e.to]==cnt[Minnum]+1)
{
//消灭的敌数
if(sumnum[e.to]<sumnum[Minnum]+num[e.to])
{
sumnum[e.to]=sumnum[Minnum]+num[e.to];
pred[e.to]=Minnum;
}
}
}
}
}
}
void dfs(int *p,int x,vector<int>& a)
{
if(x==s)
{
a.push_back(x);
return ;
}
dfs(p,p[x],a);
a.push_back(x);
}
int main()
{
string city[N]; //表示字符串,对应mp表示字符串对应的数字
string city1,city2;
cin>>n>>k>>city1>>city2;
city[0]=city1;
mp[city1]=0;
for(int i=1;i<n;i++)
{
cin>>city[i]>>w;
mp[city[i]]=i; //建立映射,便于查找
num[i]=w; //存储军队的个数
}
s=0; //开始城市的序号
des=mp[city2]; //目标城市序号
string a,b;
int w;
int u,v;
for(int i=0;i<k;i++)
{
cin>>a>>b>>w;
u=mp[a];
v=mp[b];
G[u].push_back({v,w}); //存储信息,相当于双向边
G[v].push_back({u,w});
}
dijkstra();
dfs(pred,des,ljd); //前一个节点 ,目标点,最短路径
//输出最合适的进攻路径
cout<<city[0];
for(int i=1;i<ljd.size();i++)
cout<<"->"<<city[ljd[i]];
//输出最快进攻路径的条数,最短进攻距离,歼敌总数
printf("\n%d %d %d",cntshort[des],dis[des],sumnum[des]);
return 0;
}
代码二、使用优先队列,思路更清晰
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N = 205;
int n,k,t,val[N],dis[N],cnt[N],num[N],lib[N];
int pre[N];
bool vis[N],flag;
vector<PII> mar[N];
string s,d,str,ptr;
unordered_map<string,int> m1;
unordered_map<int,string> m2;
void Print(int x){
if(x == 0) return;
Print(pre[x]);
if(flag) cout << "->";
else flag = 1;
cout << m2[x];
}
void Dijkstra(int s) {
memset(dis,0x3f,sizeof(dis));
priority_queue<PII,vector<PII>,greater<PII>> qu;
qu.push({0,s});
cnt[s] = 1,dis[s] = 0;
while(!qu.empty()) {
int u = qu.top().y;
qu.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = 0; i < mar[u].size(); ++i) {
int v = mar[u][i].x,w = mar[u][i].y;
if(dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
cnt[v] = cnt[u];
lib[v] = lib[u] + 1;
num[v] = num[u] + val[v];
pre[v] = u;
qu.push({dis[v],v});
} else if(dis[v] == dis[u] + w) {
cnt[v] += cnt[u];
if(lib[v] < lib[u] + 1) {
lib[v] = lib[u] + 1;
num[v] = num[u] + val[v];
pre[v] = u;
} else if(lib[v] == lib[u] + 1 && num[v] < num[u] + val[v]) {
num[v] = num[u] + val[v];
pre[v] = u;
}
qu.push({dis[v],v});
}
}
}
int p = m1[d];
Print(p);
cout << endl;
cout << cnt[p] << " " << dis[p] << " " << num[p] << endl;
}
int main() {
cin >> n >> k >> s >> d;
m1[s] = 1,m2[1] = s;
for(int i = 2; i <= n; ++i) {
cin >> str >> t;
m1[str] = i;
m2[i] = str;
val[i] = t;
}
for(int i = 0; i < k; ++i) {
cin >> str >> ptr >> t;
int a = m1[str],b = m1[ptr];
mar[a].push_back({b,t});
mar[b].push_back({a,t});
}
Dijkstra(1);
return 0;
}
本文探讨了Dijkstra算法的两种实现方式,包括常规的算法实现及其复杂性,以及利用优先队列来优化思路,提高了算法的效率。

被折叠的 条评论
为什么被折叠?



