原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790
Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 Input 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。 Output 输出 一行有两个数, 最短距离及其花费。 Sample Input 3 2 1 2 5 6 2 3 4 5 1 3 0 0 Sample Output 9 11 |
根据我的总结,dijsktra有多种形式:
- 一个起点,一个终点;
- 多个起点,一个终点;https://blog.csdn.net/qq_37241934/article/details/81117775
- 多个地点,多个终点;https://blog.csdn.net/qq_37241934/article/details/81109068
- 一个起点,多个终点
这个题是一个起点一个终点。
坑点:一是注意重边最短路径,二是注意相同路径最少花费。
if(mat[a][b]>d)//注意有重边,mat代表路径
{ mat[a][b]=d;
mat[b][a]=d;
map[a][b]=map[b][a]=p;
}
else if(mat[a][b]==d)//注意边和距离都相同,取花费小的。
{
if(map[a][b]>p)//map代表花费
map[a][b]=p;
}
同样都是模板,直接上代码:
#include <stdio.h>
#include<string.h>
#define maxn 0x6fffffff
#include<iostream>
using namespace std;
int mat[1005][1005],n,m,c,t;//mat代表路径
int dist[1005],dis[1005],map[1005][1005];//map代表花费
void dijkstra()
{
int vis[1005],i,j;
for(i=1;i<=n;i++)
{
dist[i]=mat[c][i];
dis[i]=map[c][i];
vis[i]=0;
}
dist[c]=0;
dis[c]=0;
vis[c]=1;
for(i=1;i<=n;i++)
{
int mindist=maxn;
int minpos=0;
for(j=1;j<=n;j++)
if(!vis[j]&&dist[j]<mindist)
{
minpos=j;
mindist=dist[j];
}
vis[minpos]=1;
for(j=1;j<=n;j++)
{
if(!vis[j]&&(dist[minpos]+mat[minpos][j]<dist[j]))
{
dist[j]=dist[minpos]+mat[minpos][j];
dis[j]=dis[minpos]+map[minpos][j];
}
else if(dist[minpos]+mat[minpos][j]==dist[j])
{
if(dis[minpos]+map[minpos][j]<dis[j])
dis[j]=dis[minpos]+map[minpos][j];
}
}
}
return ;
}
int main()
{
int i,j,k,a,b,d,p;
while(~scanf("%d %d",&n,&m)&&n&&m)
{
for(i=0;i<1005;i++)
for(j=0;j<1005;j++)
map[i][j]=mat[i][j]=maxn;
for(i=0;i<m;i++)
{
scanf("%d %d %d %d",&a,&b,&d,&p);
if(mat[a][b]>d)//注意有重边
{ mat[a][b]=mat[b][a]=d;
map[a][b]=map[b][a]=p;
}
else if(mat[a][b]==d)//注意距离相同,取花费小的。
{
if(map[a][b]>p)
map[a][b]=map[b][a]=p;
}
}
scanf("%d %d",&c,&t);
dijkstra();
printf("%d %d\n",dist[t],dis[t]);
}
return 0;
}