题目1008:最短路径问题
时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:5386
解决:1717
-
题目描述:
-
给你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
-
来源:
- 2010年浙江大学计算机及软件工程研究生机试真题
- c++代码:
-
//1008 最短路径问题 //Dijkstra #include<cstdio> #include<vector> #include<cstring> #define INF 0x7FFFFFFF using namespace std; const int NMAX = 1000+1; struct edge { int next; int distance; int cost; edge(int b,int d,int p) { next=b,distance=d,cost=p; } }; vector<edge> eg[NMAX];//记录连接点 int dis[NMAX]; int cost[NMAX]; bool mark[NMAX]; vector<int> vt; //已选队列 void init() { memset(dis,-1,sizeof(dis));//不可达 memset(cost,0,sizeof(cost)); memset(mark,false,sizeof(mark)); for(int i=1; i<NMAX; ++i) eg[i].clear(); vt.clear(); } int main(void) { int n,m; while(~scanf("%d%d",&n,&m) && n &&m) { init(); while(m--) { int a,b,d,p; scanf("%d%d%d%d",&a,&b,&d,&p); eg[a].push_back(edge(b,d,p)); eg[b].push_back(edge(a,d,p)); } int start,end; scanf("%d%d",&start,&end); dis[start] = 0; mark[start] = true; vt.push_back(start); for(int i=1; i<=n; ++i)//n遍 { int min = INF; int minp = -1; int mincost = -1; int j = 0; while(j<vt.size())//已选入的进行遍历 { int cor = vt[j]; int size = eg[cor].size(); for(int k=0; k<size; ++k) { int tp = eg[cor][k].next; if(mark[tp]==false) { if((dis[cor]>=0 && dis[cor]+eg[cor][k].distance<min) || (dis[cor]+eg[cor][k].distance==min && cost[cor]+eg[cor][k].cost<mincost))//核心(最短距离,距离一样代价最短优先) { min = dis[cor]+eg[cor][k].distance; minp = tp; mincost = cost[cor] + eg[cor][k].cost; } } } j++; } mark[minp] = true; dis[minp] = min; cost[minp] = mincost; vt.push_back(minp); } printf("%d %d\n",dis[end],cost[end]); } return 0; }