给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
(1<n<=1000, 0<m<100000, s != t)
3 2 1 2 5 6 2 3 4 5 1 3 0 0
9 11
做法:用dijkstra经过每个点时,假设遇到两条路径到当前点,就更新下最小消费
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define maxn 1010
#define inf 0x3f3f3f3f3f3f
using namespace std;
typedef long long ll;
ll d[maxn][maxn];
ll p[maxn][maxn];
ll disd[maxn];
ll disp[maxn];
int n,m;
void dijkstra(int st)
{
int vis[maxn];
for(int i=1;i<=n;i++)
{
vis[i]=0;
disd[i]=d[st][i];
disp[i]=p[st][i];
}
vis[st]=1;
disd[st]=0;
disp[st]=0;
int mindis=inf;
int k;
for(int i=0;i<n;i++)
{
mindis=inf;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&mindis>disd[j])
{
mindis=disd[j];
k=j;
}
}
vis[k]=1;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&disd[j]>disd[k]+d[k][j])
{
disd[j]=disd[k]+d[k][j];
disp[j]=disp[k]+p[k][j];
}
else if(!vis[j]&&disd[j]==disd[k]+d[k][j])
{
if(disp[j]>disp[k]+p[k][j])
{
disp[j]=disp[k]+p[k][j];
}
}
}
}
}
void init()
{
memset(d,inf,sizeof(d));
memset(p,inf,sizeof(p));
}
int main()
{
ll a,b,c,w;
while(scanf("%d%d",&n,&m)==2)
{
if(n==0&&m==0)break;
init();
for(int i=0;i<m;i++)
{
scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&w);
if(c==d[a][b])
{
p[a][b]=min(p[a][b],w);
p[b][a]=p[a][b];
}
else if(c<d[a][b])
{
d[a][b]=d[b][a]=c;
p[a][b]=p[b][a]=w;
}
}
int st,ed;
scanf("%d%d",&st,&ed);
dijkstra(st);
printf("%I64d %I64d\n",disd[ed],disp[ed]);
}
return 0;
}