problem

最短路径问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 51476 Accepted Submission(s): 14365

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

Source
浙大计算机研究生复试上机考试-2010年

Recommend
notonlysuccess

solution

#include <bits/stdc++.h>
using namespace std;
const int maxn=1010;
const int inf = 99999999;

int n, m, s, t;
int e[maxn][maxn], e2[maxn][maxn];
int dist[maxn], cost[maxn], vis[maxn];

int main(){
ios::sync_with_stdio(false);
while(cin>>n>>m &&n+m){
memset(e,0x3f,sizeof(e));
memset(e2,0x3f,sizeof(e2));
for(int i = 1; i <= m; i++){
int a, b, w, w2;
cin>>a>>b>>w>>w2;
if(e[a][b]>w){
e[a][b] = e[b][a] = w;
e2[a][b] = e2[b][a] = w2;
}
if(e[a][b]==w && e2[a][b]>w2){
e2[a][b] = e2[b][a] = w2;
}
}
cin>>s>>t;
memset(dist,0x3f,sizeof(dist));
memset(cost,0x3f,sizeof(cost));
memset(vis,0,sizeof(vis));
dist[s] = cost[s] = 0;
for(int i = 1; i <= n; i++){
int u = -1, minn = inf;
for(int j = 1; j <= n; j++){
if(!vis[j] && dist[j]<minn)
{ u = j; minn = dist[j]; }
}
vis[u] = 1;
for(int j = 1; j <= n; j++){
if(dist[j]>dist[u]+e[u][j]){
dist[j]=dist[u]+e[u][j];
cost[j]=cost[u]+e2[u][j];
}else if(dist[j]==dist[u]+e[u][j] && cost[j]>cost[u]+e2[u][j]){
cost[j]=cost[u]+e2[u][j];
}
}
}
cout<<dist[t]<<" "<<cost[t]<<"\n";
}
return 0;
}