1030 Travel Plan (30 分) 题解(dijkstra+dfs)
题目传送门
解题思路:
题目要求我们计算出从起点到终点的最短路径,所以需要使用最短路算法将最短路径算出来,此外可能会存在多条最短路径,我们需要将保存并输出花费最小的最短路径。于是我们就可以用一个数组来存储最短路径上节点的前驱节点,再利用深度优先搜索逆向遍历一边就可以得到我们的正确路径。这里我们使用邻接表来存储图。
要注意边的个数问题,我第一次出错就在于没有开足够大的空间来存储边。
代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=510*510;//这里要开大一些
int n,m,s,d;
int h[N],e[N],ne[N],w[N],c[N],idx;
void add(int a,int b,int dis,int cost)
{
e[idx]=b;
w[idx]=dis;
c[idx]=cost;
ne[idx]=h[a];
h[a]=idx++;
}
int dist[N];
int cost[N];
bool vis[N];
vector<int> path(N);
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
memset(cost,0x3f,sizeof cost);
cost[s]=0;
dist[s]=0;
priority_queue<PII,vector<PII>,greater<PII> >heap;
heap.push({0,s});
while(heap.size())
{
auto t=heap.top();
heap.pop();
int v=t.second,dis=t.first;
if(vis[v]) continue;
vis[v]=true;
for(int i=h[v];i!=-1;i=ne[i])
{
int u=e[i];
if(dist[u]>dis+w[i])//这里是主要逻辑
{
dist[u]=dis+w[i];
cost[u]=cost[v]+c[i];
path[u]=v;
heap.push({dist[u],u});
}
else if(dist[u]==dis+w[i])
{
if(cost[u]>cost[v]+c[i])
{
cost[u]=cost[v]+c[i];
path[u]=v;
}
}
}
}
}
vector<int> ans;
void dfs(int u)
{
if(u==s)
{
ans.push_back(u);
for(int i=ans.size()-1;i>=0;i--)
{
printf("%d ",ans[i]);
}
printf("%d %d",dist[d],cost[d]);
return;
}
ans.push_back(u);
dfs(path[u]);
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&d);
memset(h,-1,sizeof h);
for(int i=0;i<m;i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
add(a,b,c,d),add(b,a,c,d);
}
dijkstra();
dfs(d);
return 0;
}