POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3790
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
Source
题意描述:
输入顶点的个数n和道路的条数m以及起始点数s和t((1<n<=1000, 0<m<100000, s != t))
计算并输出最短距离及其花费(如果最短路径数相同,输出花费最小)
解题思路:
哇,读到这个题,心想求最短路径和最小花费,直接两边DijkstraOK,直接WA。
后来想想,先要保证路径最短,那么就先求最短路径,Dijkstra不变,只不过最后更新的时候处理一下最小花费就行了,具体处理方法见代码。
另外,既然存在路径相同而花费不同,那么必然输入数据存在两顶点相同,路径相同,但花费不同的数据,所以输入的时候我们只保留相同情况下花费最小即可。
题目很经典,如需了解
最长路径最小权值 请参考博客:http://www.cnblogs.com/wenzhixin/p/7336948.html
最短路径最大权值 请参考博客:http://www.cnblogs.com/wenzhixin/p/7406333.html
AC代码:
1 #include<stdio.h> 2 int e1[1010][1010],e2[1010][1010]; 3 int inf=99999999,n,m,s,t; 4 void Dijkstra(); 5 int main() 6 { 7 int i,j,t1,t2,t3,t4; 8 while(scanf("%d%d",&n,&m), n+m != 0) 9 { 10 for(i=1;i<=n;i++)//全部初始化为inf 11 for(j=1;j<=n;j++) 12 e1[i][j]=e2[i][j]=inf;//i和j 13 14 for(i=1;i<=m;i++) 15 { 16 scanf("%d%d%d%d",&t1,&t2,&t3,&t4); 17 if(e1[t1][t2] > t3)//存储的时候就去重,先保证路径最短,否则如 18 //果相等且花费变小则更新花费 19 { 20 e1[t1][t2]=e1[t2][t1]=t3;//双向 21 e2[t1][t2]=e2[t2][t1]=t4; 22 } 23 else if(e1[t1][t2] == t3 && e2[t1][t2] > t4) 24 e2[t1][t2]=e2[t2][t1]=t4; 25 } 26 scanf("%d%d",&s,&t); 27 28 Dijkstra(); 29 } 30 return 0; 31 } 32 void Dijkstra() 33 { 34 int i,j,u,v,min,d[1010],c[1010],book[1010]; 35 for(i=1;i<=n;i++) 36 { 37 d[i]=e1[s][i]; 38 c[i]=e2[s][i]; 39 } 40 for(i=1;i<=n;i++) 41 book[i]=0;//初始化为0 42 book[s]=1; 43 44 for(i=1;i<=n-1;i++) 45 { 46 min=inf; 47 for(j=1;j<=n;j++) 48 {//找到距离s点最近的尚未访问的点 49 if(!book[j] && d[j] < min) 50 { 51 min=d[j]; 52 u=j; 53 } 54 } 55 book[u]=1; 56 for(v=1;v<=n;v++)//遍历每个顶点 57 { 58 if(!book[v] && e1[u][v] < inf) 59 {//加入点U后,更新每个顶点到s的距离为最近,便于下次查找 60 if(d[v] > d[u]+e1[u][v]) 61 {//和之前的去重一样,在保证最短路径且花费减少时 才更新最小花费 62 d[v]=d[u]+e1[u][v]; 63 c[v]=c[u]+e2[u][v]; 64 } 65 else if(d[v] == d[u]+e1[u][v] && c[v] > c[u]+e2[u][v]) 66 c[v] = c[u]+e2[u][v]; 67 } 68 } 69 } 70 printf("%d %d\n",d[t],c[t]); 71 }
欢迎交流,共同进步——