题解 | 最短路径问题
最短路径问题
https://www.nowcoder.com/practice/e372b623d0874ce2915c663d881a3ff2
#include <cstdio> #include <iostream> #include <cstring> using namespace std; int n,m; struct PII{ int d; //距离 int p; //花费 PII(int d,int p):d(d),p(p){} PII():d(0),p(0){} //无参数构造函数,默认初始化d和p为0; //定义有参构造函数后,必须再手动定义一个无参构造函数,用于声明全局结构体数组时给系统使用; }; const int N = 1010; PII g[N][N],dist[N]; bool s[N]; void Dijkstra(int start,int end){ dist[start].d=0; dist[start].p=0; for(int i=0;i<n;i++){ int t=-1; for(int j=1;j<=n;j++){ if(!s[j] && (t==-1 || dist[j].d<dist[t].d)){ //t==-1 别写成赋值t=-1 t=j; } } s[t]=true; for(int j=1;j<=n;j++){ if(!s[j] && g[t][j].d!=0x3f3f3f3f){ if(dist[t].d+g[t][j].d<dist[j].d){ //如果从t到j的距离更短,则更新距离和花费,哪怕花费更高也更新 dist[j].d=dist[t].d+g[t][j].d; dist[j].p=dist[t].p+g[t][j].p; }else if(dist[t].d+g[t][j].d==dist[j].d){ //如果两距离一样,则选花费低的 dist[j].p=min(dist[j].p,dist[t].p+g[t][j].p); } } } } if(dist[end].d==0x3f3f3f3f)printf("-1"); else printf("%d %d",dist[end].d,dist[end].p); } PII mymin(PII a,PII b){ if(a.d<b.d){ return a; }else if(a.d>b.d){ return b; } return a.p<b.p?a:b; } int main() { while (scanf("%d%d",&n,&m)!=EOF) { //scanf("%d%d",&n,&m)!=EOF 避免死循环 if(m==0 && n==0){ break; } //重置PII g[N][N]h和dist[N]数组 以及标记数组s for(int i = 1;i<=n;i++){ dist[i]=PII(); s[i]=false; } for(int i = 1;i<=n;i++){ for(int j = 1;j<=n;j++){ g[i][j]=PII(); } } while(m--){ int a,b,d,p; scanf("%d%d%d%d",&a,&b,&d,&p); // 处理重边,保留更优的边 g[a][b] = mymin(PII(d, p),g[a][b]); g[b][a] = mymin(PII(d, p),g[b][a]);; // 无向图 } int s,t; scanf("%d%d",&s,&t); Dijkstra(s, t); } } // 64 位输出请用 printf("%lld")
【关键点】:
- 每次换下一组测试用例时,记得重置 g[N][N]、dist[N] 以及标记数组s[N];
- 因为这是无向图,也就是说当题目输入a->b,b->a 两条距离和花费不一样的边时,选择一个最优的就行;因此要处理重边:
- 在Dijkstra算法中根据节点t更新其他节点时:距离的优先级要大于花费,在距离相同的情况下,才选花费少的;否则优先选距离短的;