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
//这个跟最短路径是一样的做法,只不过是加多花费的更新而已。
#include <iostream>
#include <cstring>
#include <cstdio>
#define maxDis 999999999
#define maxN 1005
using namespace std;
int road[maxN][maxN][2];
int dis[maxN]; //保存一个点到另一个点的路径长度。
int cost[maxN]; //保存一个点到某一个点的花费。
bool visit[maxN];
void minLength(int s,int t,int n)
{
for(int i = 1 ; i <= n; i++)
{
visit[i] = false;
dis[i] = road[s][i][0];
cost[i] = road[s][i][1];
}
dis[s] = 0;
cost[s] = 0;
visit[s] = true;
for(int i = 1 ; i <= n; i++)
{
int min = maxDis;
int index = 0;
for(int j = 1 ; j <= n; j++)
{
if(!visit[j] && dis[j] < min)
{
min = dis[j];
index = j;
}
}
visit[index] = true;
for(int j = 1 ; j <= n; j++)
{
if(!visit[j] && road[index][j][0] < maxDis && dis[index] + road[index][j][0] < dis[j])
{
dis[j] = dis[index] + road[index][j][0];
cost[j] = cost[index] + road[index][j][1];
}
else if(!visit[j] && dis[index] + road[index][j][0] == dis[j])//当路径长度相同的时候,加多花费的更新
{
if(cost[j] > cost[index] + road[index][j][1])
{
cost[j] = cost[index] + road[index][j][1];
}
}
}
}
cout<<dis[t]<<" "<<cost[t]<<endl;
}
int main()
{
int n,m;
while(cin>>n>>m && n && m)
{
for(int i = 1 ; i <= n; i++)
{
for(int j = 1 ; j <= n; j++)
{
if(i == j)
{
road[i][j][0] = 0;
road[i][j][1] = 0;
}
else
{
road[i][j][1] = maxDis;
road[i][j][0] = maxDis;
}
}
}
int a,b,x,p;
for(int i = 0 ; i < m ;i++)
{
//cin>>a>>b>>x>>p;
scanf("%d%d%d%d",&a,&b,&x,&p);//用cin会超时,所以用scanf读入数据。。。
if (road[a][b][0] > x)
{
road[a][b][0] = x;
road[b][a][0] = x;
road[a][b][1] = p;
road[b][a][1] = p;
}
}
int s,t;
cin>>s>>t;
if(s > t)
{
minLength(s,t,n);
}
else
{
minLength(t,s,n);
}
}
return 0;
}