九度OJ:题目1008 最短路径问题

题目描述:
给你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

[解题思路]

构造无向图,运用Dijkstra算法求最短路径,在求最短路径的同时求出最小花费(注意重边)。

消除重边影响的代码如下

<span style="font-size:14px;">		</span><span style="font-size:18px;">for(i=1;i<=M;i++){
			int s,e,w,c;
			scanf("%d %d %d %d",&s,&e,&w,&c);
			if(map[s][e]>w||(map[s][e]==w&&cost[s][e]>c)) {
				map[s][e]=map[e][s]=w;
				cost[s][e]=cost[e][s]=c;
			}
		}</span>
本题目所运用的Dijkstra算法的改动版本为:

<span style="font-size:18px;">void Dijkstra(){
    int i,j;
    memset(visited,false,sizeof(visited));
    for(i=1;i<=N;i++){
        dist[i]=map[S][i];
        mon[i]=cost[S][i];
        if(dist[i]!=MAX){
            insert(i);
            visited[i]=true;
        }
    }
    dist[S]=0;
    mon[S]=0;
    while(l!=NULL){
        int m=getMin();
        for(j=1;j<=N;j++){
            if(map[m][j]!=MAX){
                if(dist[j]>dist[m]+map[m][j]){
                    dist[j]=dist[m]+map[m][j];
                    mon[j]=mon[m]+cost[m][j];
                }
				/*
				*如果有相同长度的路径,花费选择较少的那个
				*/
                else if(dist[m]+map[m][j]==dist[j]&&mon[m]+cost[m][j]<mon[j])
                {
                    mon[j]=mon[m]+cost[m][j];
                }
                if(visited[j]==false) insert(j);
                visited[j]=true;
            }
        }
    }
}</span>
所以该题的源代码如下:

<span style="font-size:18px;">#include<malloc.h>
#include<stdio.h>
#include<string.h>
#define R 1001
#define C 1001
#define MAX 10000000
 
typedef struct Node* link;
struct Node{
    int e;
    link next;
};
 
link l;
int M,N,S,E;
int map[R][C];
int count;
int dist[R],mon[R],cost[R][C];
bool visited[R]={0};
//int sum[R]={0};
 
void insert(int x){
    if(l==NULL){
        link p=(link)malloc(sizeof(Node));
        p->e=x;
        l=p;
        l->next=NULL;
    }
    else{
        link p=(link)malloc(sizeof(Node));
        p->e=x;
        p->next=l->next;
        l->next=p;
    }
    return;
}
int getMin(){
    if(l->next==NULL){
        int x=l->e;
        l=NULL;
        return x;
    }
    else{
        link p=l;
        link r=l;
        link q=l->next;
        link t=l;
        while(q!=NULL){
            if(dist[q->e]<dist[p->e]){
                t=r;
                p=q;
            }
            r=q;    
            q=q->next;
        }
        int x=p->e;
        if(p==l){
            l=l->next;
            free(p);
        }
        else{
            t->next=p->next;
            free(p);
        }
        return x;
    }
}
void Dijkstra(){
    int i,j;
    memset(visited,false,sizeof(visited));
    for(i=1;i<=N;i++){
        dist[i]=map[S][i];
        mon[i]=cost[S][i];
        if(dist[i]!=MAX){
            insert(i);
            visited[i]=true;
        }
    }
    dist[S]=0;
    mon[S]=0;
    while(l!=NULL){
        int m=getMin();
        for(j=1;j<=N;j++){
            if(map[m][j]!=MAX){
                if(dist[j]>dist[m]+map[m][j]){
                    dist[j]=dist[m]+map[m][j];
                    mon[j]=mon[m]+cost[m][j];
                }
				/*
				*如果有相同长度的路径,花费选择较少的那个
				*/
                else if(dist[m]+map[m][j]==dist[j]&&mon[m]+cost[m][j]<mon[j])
                {
                    mon[j]=mon[m]+cost[m][j];
                }
                if(visited[j]==false) insert(j);
                visited[j]=true;
            }
        }
    }
}
int main(){
    int i,j;
    while(scanf("%d %d",&N,&M)==2&&N&&M){
        for(i=1;i<=N;i++){
            for(j=1;j<=N;j++){
                cost[i][j]=cost[j][i]=MAX;
                map[i][j]=map[j][i]=MAX;
            }
            dist[i]=MAX;
        }
        for(i=1;i<=M;i++){
            int s,e,w,c;
            scanf("%d %d %d %d",&s,&e,&w,&c);
            if(map[s][e]>w||(map[s][e]==w&&cost[s][e]>c)) {
                map[s][e]=map[e][s]=w;
                cost[s][e]=cost[e][s]=c;
            }
        }
        scanf("%d %d",&S,&E);
        Dijkstra();
         
        printf("%d %d\n",dist[E],mon[E]);
        free(l);
        l=NULL;
    }
}</span>
[题目网址]
http://ac.jobdu.com/problem.php?pid=1008



你可能感兴趣的:(数据结构,算法,九度OJ)