最短路径问题
Time Limit: 2000/1000 MS (Java/Others) | Memory Limit: 32768/32768 K (Java/Others) |
---|
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)
Output
输出 一行有两个数, 最短距离及其花费。
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
相较于POJ -2387 Til the Cows Come Home(Dijkstra,Bellman-Ford)多了一个价钱而已,并且它是跟着最短路径更新的同时更新
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int N=1005;
struct date
{
int from, to, dic, price;
};
date ee[N*100];
int dist[N], price[N];
int n, m;
int st, en;
int bellman_ford()
{
for(int i=1; i<=n; i++)
dist[i]=INF;
dist[st]=0;
price[st]=0;
while(1)
{
int flag=0;
for(int i=0; i<m; i++)
{
date e=ee[i];
if(e.dic+dist[e.from]<dist[e.to])//因为是无向图,起点到终点,终点到起点都要判断一次
{
dist[e.to]=e.dic+dist[e.from];
price[e.to]=e.price+price[e.from];
flag=1;
}
else if(e.dic+dist[e.to]<dist[e.from])
{
dist[e.from]=e.dic+dist[e.to];
price[e.from]=e.price+price[e.to];
flag=1;
}
}
if(flag==0)//本次循环没有再更新
return 1;//没有负环回路
}
for(int i=0; i<m; i++)
{
date e=ee[i];
if(e.dic+dist[e.from]<dist[e.to])
return 0;//有负环回路
if(e.dic+dist[e.to]<dist[e.from])
return 0;//有负环回路
}
return 1;//没有负环回路
}
int main()
{
while(scanf("%d%d", &n, &m), n||m)
{
for(int i=0; i<m; i++)
{
scanf("%d%d%d%d", &ee[i].from, &ee[i].to, &ee[i].dic, &ee[i].price);
}
scanf("%d%d", &st, &en);
memset(price, 0, sizeof(price));
bellman_ford();
printf("%d %d\n", dist[en], price[en]);
}
return 0;
}