图(最短路径)2

来源:互联网 发布:钢琴软件 电脑版 编辑:程序博客网 时间:2024/06/06 19:40
/*
题目1008:最短路径问题   dijkstra算法 时间复杂度n^2 空间复杂度 n
题目描述:
给你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
*/
#include <stdio.h>
#include <vector>
using namespace std;
struct E{//邻接链表元素结构体
int next;
int c;
int cost;
};
vector<E> edge[1001];//邻接链表
int dis[1001];//距离数组
int cost[1001];//花费数组
bool mark[1001];//是否属于集合K数组
int main(){
int n,m,i,j;
int S,T;//起点,终点
while(scanf("%d%d",&n,&m) != EOF){
if(n==0 && m==0) break;
for(i=1;i<=n;i++) edge[i].clear();//初始化邻接链表
while(m--){
int a,b,c,cost;
scanf("%d%d%d%d",&a,&b,&c,&cost);
E tmp;
tmp.c = c;
tmp.cost = cost;//邻接链表中增加了该边的花费信息
tmp.next = b;
edge[a].push_back(tmp);
tmp.next = a;
edge[b].push_back(tmp);
}
scanf("%d%d",&S,&T);//输入起点终点信息
for(i=1;i<=n;i++){//初始化
dis[i] = -1;
mark[i] = false;
}
dis[S] = 0;
mark[S] = true;
int newp = S;//起点为S,将其加入集合K,且其最短距离确定为0
for(i=1;i<n;i++){
for(j=0;j<edge[newp].size();j++){
int t = edge[newp][j].next;
int c = edge[newp][j].c;
int co = edge[newp][j].cost;//花费
if(mark[t] == true) continue;
if(dis[t] == -1 || dis[t] > dis[newp] + c || dis[t] == dis[newp]+c && cost[t]>cost[newp] + co){
//比较大小,将距离相同但花费更短也作为更新条件之一
dis[t] = dis[newp] + c;
cost[t] = cost[newp] + co;//更新花费
}
}
int min = 123123123;
for(j=1;j<=n;j++){//选择最小值,选择时不用考虑花费的因素,
//因为距离最近的点的花费已经不可能由于经过其它点而发生改变了
if(mark[j] == true) continue;
if(dis[j] == -1) continue;
if(dis[j] < min){
min = dis[j];
newp = j;
}
}
mark[newp] = true;
}
printf("%d %d\n",dis[T],cost[T]);//输出答案
}
return 0;
}


0 0
原创粉丝点击