题目描述
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
输入
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
输出
输出 一行有两个数, 最短距离及其花费。
样例输入
3 2
1 2 5 6
2 3 4 5
1 3
0 0
样例输出
9 11
思路:题面已经讲的很清楚了,需要注意,路径有两个权值,用dijsktra就可以解决,只不过我自己被提示带歪,用了dfs来写这道题,递归又成了硬伤,昨天才被吐槽过,不会递归还用什么dfs。。。
自己错的地方如下:
1:初始化。标记数组应该全部初始化为不能通过,即-1,输入边时,能通过一条边就将这条边初始化为0.
2:递归出口。到达终点并不是结束条件,只有点全部搜索完才结束,然后回溯。
3:更新最短距离和花费的条件。有两种情况:一种是最短距离相等时,比较花费,一种是最短距离不等,直接比较最短距离。
#include<stdio.h> #include<string.h> #define N 1010 #define inf 0x3f3f3f3f int n,m,ans,min1,min2,cost,head,tail,sum1,sum2; int book[N][N]; int dis[N],w[N]; struct node{ int len,cost; }; node e[N][N]; void dfs(int x,int c,int d) { int y,i; if(x > n) return ; if(x == tail) { if(d < min1||d == min1 && c < min2) { min1 = d; min2 = c; } } for(i = 1; i <= tail; i ++) if(book[x][i]==0) { book[x][i] = -1; dfs(i,c+e[x][i].cost,d+e[x][i].len); book[x][i] = 0; } return; } int main() { int i,j,t1,t2,t3,t4,u; while(scanf("%d%d",&n,&m),(n+m)!=0) { memset(book,-1,sizeof(book)); for(i = 1; i <= m; i ++) { scanf("%d%d%d%d",&t1,&t2,&t3,&t4); e[t1][t2].len = t3; e[t2][t1].len = t3; e[t1][t2].cost = t4; e[t2][t1].cost = t4; book[t1][t2] = 0; book[t2][t1] = 0; } scanf("%d%d",&head,&tail); min1 = min2 = inf; dfs(head,0,0); printf("%d %d ",min1,min2); } return 0; }