Problem Description
做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。
Input
连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。
Output
在同一行中输出路径长度和收费总额,数据间用空格间隔。
Sample 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 20Sample Output
3 40
- #include<bits/stdc++.h>
- using namespace std;
- #define INF 0x3f3f3f3f
- #define MAXN 510
- int mp[MAXN][MAXN];
- int cost[MAXN][MAXN];
- int dis[MAXN]; //原点v0到vi最短路径长度
- int vis[MAXN]; //标记数组
- int mon[MAXN];
- void Dijkstra(int n, int v0, int vn)
- {
- int i, j;
- for(i = 0; i < n; i++)
- {
- dis[i] = mp[v0][i];
- mon[i] = cost[v0][i];
- }
- memset(vis, 0, sizeof(vis));
- vis[v0] = 1;
- dis[v0] = 0;
- mon[v0] = 0;
- for(i = 1; i < n; i++)
- {
- int Min = INF;
- int k = v0;
- for(j = 0; j < n; j++) //选择当前集合中最短路径的顶点k
- {
- if(!vis[j] && dis[j] < Min)
- {
- Min = dis[j];
- k = j;
- }
- }
- vis[k] = 1;
- for(j = 0; j < n; j++)
- {
- if(!vis[j] && mp[k][j] < INF)
- {
- if(dis[k] + mp[k][j] < dis[j])
- {
- dis[j] = dis[k] + mp[k][j];
- mon[j] = mon[j] + cost[k][j];
- }
- }
- else if(dis[k] + mp[k][j] == dis[j] && mon[k] + cost[k][j] < mon[j])
- mon[j] = mon[j] + cost[k][j];
- }
- }
- printf("%d %d\n", dis[vn], mon[vn]);
- }
- int main()
- {
- int t, n, m, s, d, a, b, l, c;
- int i, j;
- scanf("%d", &t);
- while(t--)
- {
- scanf("%d%d%d%d", &n, &m, &s, &d);
- for(i = 0; i < n; i++)
- for(j = 0; j < n; j++)
- if(i == j) mp[i][j] = 0;
- else mp[i][j] = INF;
- for(i = 0; i < m; i++)
- {
- scanf("%d%d%d%d", &a, &b, &l, &c);
- mp[a][b] = mp[b][a] = l;
- cost[a][b] = cost[b][a] = c;
- }
- Dijkstra(n, s, d);
- }
- }