地址:http://acm.hdu.edu.cn/showproblem.php?pid=3790
最短路径问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5246 Accepted Submission(s): 1588
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)
Output
输出 一行有两个数, 最短距离及其花费。
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
Source
Recommend
notonlysuccess
这题也纠结死了,开始的时候用floyd算法超时,然后改用Dijkstra算法 又WA了好多次,关键是忽略了输入的时候如果两点之间的路径短,则其花费一定被覆盖,不管花费是否大于原来的。
#include <stdio.h> #include <string.h> #define INF 9999999 int map[1001][1001]; int cost[1001][1001]; int n,m,a,b,d,p,s,t; int dist[1001]; bool visit[1001]; int c[1001]; /*void floyd() { int i,j,k; for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(map[i][j]>=map[i][k]+map[k][j]) { map[i][j]=map[i][k]+map[k][j]; if(cost[i][j]>cost[i][k]+cost[k][j]) cost[i][j]=cost[i][k]+cost[k][j]; } }*/ void dijkstra(int x,int y) { int next,i,j,min; memset(visit,false,sizeof(visit)); for(i=1;i<=n;i++) { dist[i]=INF; c[i]=INF; } dist[x]=0; c[x]=0; for(j=1;j<=n;j++) { min=INF; for(i=1;i<=n;i++) if(!visit[i]&&dist[i]<min) min=dist[next=i]; if(min==INF) break; visit[next]=true; for(i=1;i<=n;i++) if(!visit[i]&&dist[i]>=dist[next]+map[next][i]) { if(dist[i]==dist[next]+map[next][i]) { if( c[i]>c[next]+cost[next][i]) c[i]=c[next]+cost[next][i]; } else { dist[i]=dist[next]+map[next][i]; c[i]=c[next]+cost[next][i]; } } } } int main() { while(scanf("%d%d",&n,&m)==2&&(m+n)) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { map[i][j]=INF; cost[i][j]=INF; } while(m--) { 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; //正确的输入应该是以短路经为主,只需比较路径 } /*if(p<cost[a][b]) cost[a][b]=cost[b][a]=p;*/ //原来的输入,路径和花费分别判断 } scanf("%d%d",&s,&t); dijkstra(s,t); printf("%d %d\n",dist[t],c[t]); } return 0; }