7-13 天梯地图

思路

这题我用了两种写法,我们把数据分层读入就可以调用两次dijkstra而不用重写了。

第一种是优化的dijkstra,Node节点中只放id和dis的原因是,没有必要放cost,也就是题中的第二个排序的权值。

对于点A来说,假设B、C两点的dis相同,但是cost[b] < cost[c] ,假如B先到,然后优先队列里面C到了,这样C不能更新cost。假如C先到,则后到的B可以更新cost,这样其实没分别,所以Node里面没有必要放cost。

堆优化

#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=0x3f3f3f3f;
int d[maxn],dp[maxn],pre[maxn];
int vis[maxn];
int n;
vector<int> path[2];

struct Node {
    int id;
    int dis;
    Node(int i,int c):id(i), dis(c) {}
    bool operator < (const Node& a) const {
        return dis>a.dis;
    }
};

int dijkstra(int s,int e,vector<int>* g,vector<int>* dist,vector<int>* cast,int index) {
    memset(vis,0,sizeof(vis));
    memset(d,INF,sizeof(d));
    memset(dp,INF,sizeof(dp));
    memset(pre,-1,sizeof(pre));
    d[s]=0;
    dp[s]=0;
    priority_queue<Node> pq;
    pq.push(Node(s,0));
    while (!pq.empty()) {
        Node f=pq.top();
        pq.pop();
        if (vis[f.id]) {
            continue;
        }
        vis[f.id]=1;
        int from=f.id;
        int sz=g[from].size();
        for (int j=0;j<sz;j++) {
            int next=g[from][j];
            if (vis[next]) {
                continue;
            }
            int ds=dist[from][j];
            int cost=cast[from][j];
            if (d[from]+ds<d[next]) {
                d[next]=d[from]+ds;
                dp[next]=dp[from]+cost;
                pre[next]=from;
                pq.push(Node(next,d[next]));
            }
            else if (d[from]+ds==d[next]&&dp[from]+cost<dp[next]) {
                dp[next]=dp[from]+cost;
                pre[next]=from;
            }
        }
    }
    int root=e;
    while (root!=-1) {
        path[index].push_back(root);
        root=pre[root];
    }
    return d[e];
}

void printPath(vector<int> pa) {
    int sz=pa.size();
    int print=0;
    for (int i=sz-1;i>=0;i--) {
        if (!print) {
            print=1;
        }
        else {
            printf(" =>");
        }
        printf(" %d",pa[i]);
    }
    printf("\n");
}

int main()
{
    vector<int> g[4][maxn];
    int m,v1,v2,oneway,length,time;
    scanf("%d%d",&n,&m);
    while (m--) {
        scanf("%d%d%d%d%d",&v1,&v2,&oneway,&length,&time);
        g[0][v1].push_back(v2);
        g[1][v1].push_back(length);
        g[2][v1].push_back(time);
        g[3][v1].push_back(1);
        if (!oneway) {
            g[0][v2].push_back(v1);
            g[1][v2].push_back(length);
            g[2][v2].push_back(time);
            g[3][v2].push_back(1);
        }
    }
    int s,e;
    scanf("%d%d",&s,&e);
    int anstime=dijkstra(s,e,g[0],g[2],g[1],0);
    int ansdis=dijkstra(s,e,g[0],g[1],g[3],1);
    if (path[0]==path[1]) {
        printf("Time = %d; Distance = %d:",anstime,ansdis);
        printPath(path[0]);
    }
    else {
        printf("Time = %d:",anstime);
        printPath(path[0]);
        printf("Distance = %d:",ansdis);
        printPath(path[1]);
    }

    return 0;
}

普通dijkstra

#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=0x3f3f3f3f;
int d[maxn],dp[maxn],pre[maxn];
int vis[maxn];
int n;
vector<int> path[2];

struct Node {
    int id;
    int dis;
    Node(int i,int c):id(i), dis(c) {}
    bool operator < (const Node& a) const {
        return dis>a.dis;
    }
};

int dijkstra(int s,int e,vector<int>* g,vector<int>* dist,vector<int>* cast,int index) {
    memset(vis,0,sizeof(vis));
    memset(d,INF,sizeof(d));
    memset(dp,INF,sizeof(dp));
    memset(pre,-1,sizeof(pre));
    d[s]=0;
    dp[s]=0;
    for (int i=1;i<=n;i++) {
        int from=-1,tmp=INF;
        for (int j=0;j<n;j++) {
            if (!vis[j]&&d[j]<tmp){
                tmp=d[j];
                from=j;
            }
        }
        if (from==-1){
            break;
        }
        vis[from]=1;
        int sz=g[from].size();
        for (int j=0;j<sz;j++) {
            int next=g[from][j];
            if (vis[next]) {
                continue;
            }
            int ds=dist[from][j];
            int cost=cast[from][j];
            if (d[from]+ds<d[next]) {
                d[next]=d[from]+ds;
                dp[next]=dp[from]+cost;
                pre[next]=from;
            }
            else if (d[from]+ds==d[next]&&dp[from]+cost<dp[next]) {
                dp[next]=dp[from]+cost;
                pre[next]=from;
            }
        }
    }
    int root=e;
    while (root!=-1) {
        path[index].push_back(root);
        root=pre[root];
    }
    return d[e];
}

void printPath(vector<int> pa) {
    int sz=pa.size();
    int print=0;
    for (int i=sz-1;i>=0;i--) {
        if (!print) {
            print=1;
        }
        else {
            printf(" =>");
        }
        printf(" %d",pa[i]);
    }
    printf("\n");
}

int main()
{
    vector<int> g[4][maxn];
    int m,v1,v2,oneway,length,time;
    scanf("%d%d",&n,&m);
    while (m--) {
        scanf("%d%d%d%d%d",&v1,&v2,&oneway,&length,&time);
        g[0][v1].push_back(v2);
        g[1][v1].push_back(length);
        g[2][v1].push_back(time);
        g[3][v1].push_back(1);
        if (!oneway) {
            g[0][v2].push_back(v1);
            g[1][v2].push_back(length);
            g[2][v2].push_back(time);
            g[3][v2].push_back(1);
        }
    }
    int s,e;
    scanf("%d%d",&s,&e);
    int anstime=dijkstra(s,e,g[0],g[2],g[1],0);
    int ansdis=dijkstra(s,e,g[0],g[1],g[3],1);
    if (path[0]==path[1]) {
        printf("Time = %d; Distance = %d:",anstime,ansdis);
        printPath(path[0]);
    }
    else {
        printf("Time = %d:",anstime);
        printPath(path[0]);
        printf("Distance = %d:",ansdis);
        printPath(path[1]);
    }

    return 0;
}

posted @ 2020-02-17 16:25  xyee  阅读(277)  评论(0编辑  收藏  举报