Problem Description
做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。
Input
连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。
Output
在同一行中输出路径长度和收费总额,数据间用空格间隔。
Example Input
1 4 5 0 3 0 1 1 20 1 3 2 30 0 3 4 10 0 2 2 20 2 3 1 20
Example Output
3 40
Hint
Author
xam
#include<bits/stdc++.h>
#define MAX 0x3f3f3f3f
using namespace std ;
int n , m ; //顶点数,边数;
int Map[550][550] ; //点与点之间的权值;
int Money[550][550] ; //存放点与点之间的路费;
int eleco[550][550] ; //存放所有顶点到所有顶点的最短路径;
int coust[550][550] ; //存放按照点与点之间的最短路径走所需的费用;
void Forly()
{
for(int i=0;i<n;i++) //初始化eleco和coust两个二维数组;
{
for(int j=0;j<n;j++)
{
eleco[i][j] = Map[i][j] ;
coust[i][j] = Money[i][j] ;
}
}
for(int l=0;l<n;l++) //第一个for循环提供中转值,如v0->v2=5 ,v0->v1->v2=4 ,这时经过中转值的路径小于直接到的路径。 v1是中转值; (也提供验证的作用,每个点都验证,所以循环n次,看看是否相连,因为系统和程序是抽象的,无法通过看图来判断,所以要进行验证,间接判断)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i!=j)
{
if(eleco[i][j]>eleco[i][l]+eleco[l][j]) //i直接到j的路径长度大于由i到l,再由l到j的路径长度;
{
eleco[i][j] = eleco[i][l] + eleco[l][j] ;
coust[i][j] = coust[i][l] + coust[l][j] ;
}
if(eleco[i][j]==eleco[i][l]+eleco[l][j]) //路径相同,选择费用最小的;
{
if(coust[i][j]>coust[i][l]+coust[l][j])
{
coust[i][j] = coust[i][l] + coust[l][j] ;
}
}
}
}
}
}
}
int main()
{
int t ;
scanf("%d",&t);
while(t--)
{
int v0 , vn ;
scanf("%d %d %d %d",&n,&m,&v0,&vn);
int i , j ;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(i==j)
{
Map[i][j] = 0 ;
Money[i][j] = 0 ;
}
else
{
Map[i][j] = MAX ;
Money[i][j] = MAX ;
}
}
}
for(i=0;i<m;i++)
{
int u , v , h , k ;
scanf("%d %d %d %d",&u,&v,&h,&k);
Map[u][v] = Map[v][u] = h ;
Money[u][v] = Money[v][u] = k ;
}
Forly();
printf("%d %d\n",eleco[v0][vn],coust[v0][vn]);
}
return 0 ;
}