最短路径问题
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 19 Accepted Submission(s) : 5
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时输入结束。
(1<n<=1000, 0<m<100000, s != t)
(1<n<=1000, 0<m<100000, s != t)
Output
输出 一行有两个数, 最短距离及其花费。
Sample Input
3 2 1 2 5 6 2 3 4 5 1 3 0 0
Sample Output
9 11
这里要注意的是:两个点中可以有重边,特别是最短的路径的重边,应为我们求的时候只求第一个最小的的路径(以后在遇到相同的最小路径的时候,就要更新最小花费),而这条路径不能保证费用最小。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define M 1002
#define INF 1<<30
struct{
int d,cost;
} map[M][M],dist[M];
int vis[M];
int n;
int s,e;
int dijskual()
{
int i,j;
for(i=1;i<=n;i++)
{
dist[i].d=INF;
dist[i].cost=INF;
vis[i]=0;
}
dist[s].d=0;
dist[s].cost=0;
int k;
for(i=1;i<=n;i++)
{
k=-1;
for(j=1;j<=n;j++)
if(!vis[j]&&(-1==k||dist[k].d>dist[j].d))
{
k=j;
}
vis[k]=1;
if(vis[e])return 1;
for(j=1;j<=n;j++)
if(!vis[j]&&map[k][j].d&&dist[j].d>=dist[k].d+map[k][j].d)
{
if(dist[j].d>dist[k].d+map[k][j].d)
{
dist[j].d=map[k][j].d+dist[k].d;
dist[j].cost=map[k][j].cost+dist[k].cost;
}
else if(dist[j].cost>dist[k].cost+map[k][j].cost)
dist[j].cost=map[k][j].cost+dist[k].cost;
}
}
return 1;
}
int main()
{
int m,i,a,b,d,cost;
while(scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
memset(map,0,sizeof(map));
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&d,&cost);
if(map[a][b].d==0||(map[a][b].d>=d))
{
if(map[a][b].d==0||map[a][b].d>d)
{
map[a][b].d=map[b][a].d=d;
map[a][b].cost=map[b][a].cost=cost;
}
else if(map[a][b].cost>cost)
{
map[a][b].cost=map[b][a].cost=cost;
}
}
}
scanf("%d%d",&s,&e);
dijskual();
printf("%d %d\n",dist[e].d , dist[e].cost);
}
return 0;
}