Description
Input
Output
Sample Input
3 2 1 2 5 6 2 3 4 5 1 3 0 0
Sample Output
9 11
一般情况下,题目直接说XX算法问题一般考得都不是XX算法,然而这题例外。。。
这真的是一道最短路的问题,只不过是一个双权的最短路,不仅要求路径长度最短,还要求花费最少,而且路径长度是主权,花费是次权。
分析最短路算法,首先找到一个当前最短的路径lowcost[k],然后根据这条最短路以及最优子结构性质向外更新到其它点的最短路,lowcost[i]=min(lowcost[i],lowcost[k]+dis[k][i]),我们只要在
lowcost[i]==lowcost[k]+dis[k][i]的时候判断一下val[i]与val[k]+cost[k][i]的关系即可,处理方法与lowcost完全相同,只不过lowcost占主导地位。
#include <iostream> #include <cmath> #include <stdio.h> #include <string> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <iomanip> #include <algorithm> #define MAXN 1010 #define INF 0x3f3f3f3f using namespace std; int Map[MAXN][MAXN]; int cost[MAXN][MAXN]; int lowcost[MAXN]; int val[MAXN]; bool vis[MAXN]; int n,m; void dijkstra(int st,int ed) { int i,j,k,Min; for(i=1; i<=n; i++)//初始化 { lowcost[i]=INF; vis[i]=false; } val[st]=0; lowcost[st]=0; for(j=0; j<n; j++)//找到当前的一条最短路 { k=-1; Min=INF; for(i=1; i<=n; i++) { if(!vis[i]&&lowcost[i]<Min) { Min=lowcost[i]; k=i; } } if(k==-1) break; vis[k]=true; for(i=1; i<=n; i++)//判断每一个点 { if(!vis[i])//如果没有被加入最短路 { if(lowcost[k]+Map[k][i]<lowcost[i])//首先判断距离 { lowcost[i]=lowcost[k]+Map[k][i]; val[i]=val[k]+cost[k][i];//费用无条件增加 } else if(lowcost[k]+Map[k][i]==lowcost[i])//其次判断费用 { if(val[k]+cost[k][i]<val[i]) val[i]=val[k]+cost[k][i]; } } } } } int main() { int a,b,d,p,i,j; int st,ed; while(~scanf("%d%d",&n,&m)&&n&&m) { for(i=1; i<=n; i++)//初始化 for(j=1; j<=n; j++) { Map[i][j]=INF; cost[i][j]=INF; } for(i=0; i<m; i++) { scanf("%d%d%d%d",&a,&b,&d,&p); //可能会出现重边 if(Map[a][b]>d)//保留距离较短的 { Map[a][b]=Map[b][a]=d; cost[a][b]=cost[b][a]=p; } else if(Map[a][b]==d&&cost[a][b]>p)//保留费用较少的 { cost[a][b]=cost[b][a]=p; } } scanf("%d%d",&st,&ed); dijkstra(st,ed); printf("%d %d\n",lowcost[ed],val[ed]); } return 0; }