HDU3790-最短路径问题
最短路径问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 23311 Accepted Submission(s): 6963
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
解题思路:
朴素的Dij算法的基础增加额外的判断条件,在求最短路径的基础之上再去比较花费,记录最小值
源代码:
#include<iostream> #include<algorithm> #include<string> #include<cstring> #include<cmath> #include<cstdio> using namespace std; const int MAXN=1005; const int INF=0x3f3f3f3f; int Graph[MAXN][MAXN]; int Cost[MAXN][MAXN]; int s,e;//开始,结束 int m,n;//边数,顶点数 int d[MAXN];//保存最小距离 int c[MAXN];//保存最小话费 bool used[MAXN];//是否已经加入 void Dijkstra() { int v; int minpath; for(int i=1;i<=n;i++) { d[i]=Graph[s][i]; c[i]=Cost[s][i]; } memset(used,false,sizeof(used)); used[s]=true; for(int i=1;i<=n;i++) { if(used[e]) { break; } minpath=INF; for(int j=1;j<=n;j++) { if(!used[j]&&d[j]<minpath) { minpath=d[j]; v=j; } } used[v]=true; for(int j=1;j<=n;j++) { if(!used[j]&&Graph[v][j]<INF) { if(d[j]>d[v]+Graph[v][j]) { d[j]=d[v]+Graph[v][j]; c[j]=c[v]+Cost[v][j]; } else if(d[j]==d[v]+Graph[v][j]) { if(c[j]>c[v]+Cost[v][j]) { c[j]=c[v]+Cost[v][j]; } } } } } printf("%d %d\n",d[e],c[e]); } int main() { while(scanf("%d %d",&n,&m)!=EOF&&n+m) { memset(Graph,INF,sizeof(Graph)); memset(Cost,INF,sizeof(Cost)); for(int i=1;i<=n;i++) { Graph[i][i]=0; Cost[i][i]=0; } int v,u,len,money; for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&v,&u,&len,&money); if(Graph[v][u]>len) { Graph[v][u]=len;Graph[u][v]=len; Cost[v][u]=money;Cost[u][v]=money; } else if(Graph[v][u]==len) { if(Cost[v][u]>money) { Cost[v][u]=money;Cost[u][v]=money; } } } scanf("%d %d",&s,&e); Dijkstra(); } return 0; }