最短路径 | 1111

最短路径已经考腻了,已经在往模拟的趋势上发展。今天顺便还练习了一下前向星,感觉很好用,以后都用前向星了。

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 1010
#define MAX (1<<30)-1
#define V vector<int>

using namespace std;

int head[LEN];
int vis[LEN];
struct edge{
    int to,next,dist,Time;
}mp[LEN*LEN];
int eID=0;
void add(int u,int v,int dist,int Time){
    mp[eID].to=v;
    mp[eID].dist=dist;
    mp[eID].Time=Time;
    mp[eID].next=head[u];
    head[u]=eID++;
}

int N,M,s,e;
int dist[LEN];
int Time[LEN];
int pre[LEN];
int cnt[LEN];
vector<int> path1;
vector<int> path2;
int minDist;
int minTime;

void printPath(vector<int>& p){
    int sz=p.size();
    int i;
    FF(i,sz){
        O("%d",p[i]);
        if(i!=sz-1) O(" -> ");
    }
    puts("");
}

bool pathEqual(){
    if(path1.size()!=path2.size()) return false;
    int i;
    FF(i,path1.size()){
        if(path1[i]!=path2[i]) return false;
    }
    return true;
}

void dij_1(){//获得最短路径。如果最短路径不唯一,输出最快路径 
    fill(dist,dist+LEN,MAX);
    fill(Time,Time+LEN,MAX);
    fill(vis,vis+LEN,0);
    fill(pre,pre+LEN,-1);
    dist[s]=0;
    Time[s]=0;
    int i;
    while(1){
        int u=-1,min_d=MAX;
        FF(i,N) if(!vis[i] && dist[i]<min_d){
            min_d=dist[i];
            u=i;
        }
        if(u<0) break;
        vis[u]=1;
        for(i=head[u];~i;i=mp[i].next){
            int to=mp[i].to;
            if(!vis[to]){//s->u + u->to 
                if(dist[u]+mp[i].dist<dist[to] || (dist[u]+mp[i].dist==dist[to] && Time[u]+mp[i].Time<Time[to])){
                    dist[to]=dist[u]+mp[i].dist;
                    Time[to]=Time[u]+mp[i].Time;
                    pre[to]=u;
                }
            }
        }
    }
    i=e;
    while(i>=0){
        path1.insert(path1.begin(),i);
        i=pre[i];
    }
    minDist=dist[e];
}

void dij_2(){//获得最快路径。如果路径不唯一,输出经过点最少的路径 
    fill(Time,Time+LEN,MAX);
    fill(vis,vis+LEN,0);
    fill(pre,pre+LEN,-1);
    Time[s]=0;
    int i;
    while(1){
        int u=-1,min_d=MAX;
        FF(i,N) if(!vis[i] && Time[i]<min_d){
            min_d=Time[i];
            u=i;
        }
        if(u<0) break;
        vis[u]=1;
        for(i=head[u];~i;i=mp[i].next){
            int to=mp[i].to;
            if(!vis[to]){//s->u + u->to 
                if(Time[u]+mp[i].Time<Time[to] || (Time[u]+mp[i].Time==Time[to] && cnt[u]+1<cnt[to])){
                    Time[to]=Time[u]+mp[i].Time;
                    cnt[to]=cnt[u]+1;
                    pre[to]=u;
                }
            }
        }
    }
    i=e;
    while(i>=0){
        path2.insert(path2.begin(),i);
        i=pre[i];
    }
    minTime=Time[e];
}

int main(){
//    freopen("I:\pat\最短路径\1111_2.txt","r",stdin);
    memset(head,-1,sizeof(head));
    I("%d%d",&N,&M);
    int i,j,u,v,o,d,t;
    FF(i,M){
        I("%d%d%d%d%d",&u,&v,&o,&d,&t);
        add(u,v,d,t);
        if(o==0)    //不是单程路 
            add(v,u,d,t);
    }
    I("%d%d",&s,&e);
    dij_1();
    dij_2();
    if(pathEqual()){
        O("Distance = %d; Time = %d: ",minDist,minTime);
        printPath(path1);
    }else{
        O("Distance = %d: ",minDist);
        printPath(path1);
        O("Time = %d: ",minTime);
        printPath(path2);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/TQCAI/p/8593037.html