传送门
http://acm.hdu.edu.cn/showproblem.php?pid=3790 之前做过这道题,后来...后来忘了科科,思路很简单,就是迪杰斯特拉,加上一个限制条件(花费),在计算出最短路时,比较当前花费是不是同等路径长度下最少的。
错了好几次,发现是初始化存储边(两点之间的路径长度)数组时,没有直接把同等距离情况下,花费多的淘汰掉,导致存储了每次最后一个输入的路径长度和花费。
迪杰斯特拉还没掌握的可以看看下面这篇文章,我自己理解粗糙地说就是记录下起始点到各个目标点的距离,将其视为最短距离,后来若起始点经过别的点间接到达目标点的距离小于原来的最短距离,那么更新原来的最短距离(ps:批注都是后来码上去的,可能不小心删掉了源代码的一点内容?!望提醒!)
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
(之前代码好像乱了,我从hdoj上找到了题,就直接放上来了,就是没了注释)
#include<stdio.h> #include<string.h> #define MAX 1010 #define MAx 0x7fffffff int map[MAX][MAX],count[MAX][MAX]; int vis[MAX],d[MAX],pay[MAX]; int n,m; void djst(int Start) { int i,j,k,Min,index,money; vis[Start]=1; for(i=1;i<=n;i++) { d[i]=map[Start][i]; pay[i]=count[Start][i]; } for(i=1;i<n;i++) { Min=MAx; for(k=1;k<=n;k++) { if(vis[k]==0) { if(d[k]<Min) { Min=d[k];//求出d数组中的最小值min index=k;//求出d数组中的最小值的下标index } } } vis[index]=1; for(j=1;j<=n;j++) { if(vis[j]==0&&map[index][j]<MAx) { if(Min+map[index][j]<d[j]) { d[j]=Min+map[index][j];//min和d[index]和map[Start][j]是同一个概念 pay[j]=pay[index]+count[index][j]; } else if(Min+map[index][j]==d[j]) { if(pay[j]>pay[index]+count[index][j]) { pay[j]=pay[index]+count[index][j]; } } } } } } int main() { int i,j,Start,End,len,worth,a,b; while(scanf("%d %d",&n,&m)!=EOF) { if(n==0&&m==0) return 0; memset(vis,0,sizeof(vis)); memset(pay,0,sizeof(pay)); for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=count[i][j]=MAx; for(i=1;i<=m;i++) { scanf("%d %d %d %d",&a,&b,&len,&worth); if(map[a][b]>len) { count[a][b]=count[b][a]=worth; map[a][b]=map[b][a]=len; } else if(map[a][b]==len&&count[a][b]>worth) { count[a][b]=count[b][a]=worth; map[a][b]=map[b][a]=len; } } scanf("%d %d",&Start,&End); djst(Start); printf("%d %d\n",d[End],pay[End]); } return 0; }