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; }