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)
(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
题解:样例水过,就是不知道错在哪。。。可以说就是Dijkstra算法模板题,当然,除了Floyed算法外其他最短路径算法应该也可以过吧,没试。在求最短路径的基础上求花费,其实很简单,加一个cost数组用来记录最短路径的花费。在更新最短路的时候同时更新cost数组。在有多条最短路时,选择花费最小的那条。
#include<bits/stdc++.h> #define INF 0x3f3f3f3f const int maxn=1005; using namespace std; struct node{ int d,p; }e[maxn][maxn]; int dis[maxn],vis[maxn],cost[maxn]; int n,m; int s,t; void init(){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j) { e[i][j].d=0; e[i][j].p=0; } else e[i][j].d=e[i][j].p=INF; } } } void Dijkstra(){ memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++){ dis[i]=e[s][i].d; cost[i]=e[s][i].p; } cost[s]=0; vis[s]=1; dis[s]=0; for(int i=1;i<=n;i++){ int index=-1,minx=INF; for(int j=1;j<=n;j++){//寻找距离源点最近的点 if(!vis[j]&&dis[j]<minx){ minx=dis[j]; index=j; } } if(index==-1) return;//没找到说明当前所有节点已全部距离源点为最短,返回。 vis[index]=1; for(int j=1;j<=n;j++){ if(!vis[j]&&e[index][j].d){//更新最短路径 if(dis[j]>dis[index]+e[index][j].d){//最短路只有一条的情况下,同时更新最短路和花费的钱 dis[j]=dis[index]+e[index][j].d; cost[j]=cost[index]+e[index][j].p; }else if(dis[j]==dis[index]+e[index][j].d){ cost[j]=min(cost[j],cost[index]+e[index][j].p);//在有多条最短路时,选择其中花费最少的那条。 } } } } } int main() { int a,b,d,p; while(scanf("%d%d",&n,&m)&&(n+m)){ init(); for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&a,&b,&d,&p); if(d<e[a][b].d){//最短路只有一条的情况下,同时更新最短路和花费的钱 e[a][b].d=e[b][a].d=d; e[a][b].p=e[b][a].p=p; }else if(d==e[a][b].d){//在有多条最短路时,选择其中花费最少的那条。 e[a][b].p=e[b][a].p=min(p,e[a][b].p); } } scanf("%d%d",&s,&t); Dijkstra(); printf("%d %d ",dis[t],cost[t]); } return 0; }