zoukankan      html  css  js  c++  java
  • 【hihocoder #1643】最小换乘

    hihocoder #1643】最小换乘

    http://hihocoder.com/problemset/problem/1643

    时间限制:10000ms

    单点时限:1000ms

    内存限制:256MB

    描述

    Ho居住的城市有N条公交车线路,其中第i条线路上有Ki个车站。  

    某些线路之间会有公共的车站,小Ho可以在这些车站从一条线路换乘到另一条线路。  

    现在给定N条公交车线路以及两个车站SE,你能帮助小Ho计算从SE最少换乘几次公交车吗?

    输入

    第一行包含三个整数NSE  

    以下N行每行描述一条线路。第一个整数Ki代表该条线路包含的车站数。之后Ki个整数代表车站的编号。

    注意车站编号不一定连续。  

    对于50%的数据,1 ≤ N ≤ 1000,  1 ≤ Ki ≤ 100

    对于100%的数据,1 ≤ N ≤ 50000 1 ≤ Ki ≤ 800001 ≤ 所有Ki之和 ≤ 500000, 1 ≤ 车站编号 ≤ 5000000

    输出

    输出最少换乘次数。如果SE不可达,输出-1

    样例输入

    3 123 345

    4 321 375 123 456

    4 222 333 123 444

    2 222 345

    样例输出

    1

    题解:

        这个暂且叫换乘问题吧。开始误解题意是把题目当成了求最短路径的问题,毕竟两个站之间不就是一次换乘嘛。结果并不是这样。同一条路线内是不用换乘的。。。所以只有切换了路线之后才算一次换乘。

        问题的难度在规模和建图上,但是如果建好了图好像也就直接解决了规模的问题。题目的解法是新增N个虚拟的站点代表路线, 它们分别跟路线内的节点相连。最后的结果就是个二部图。

        看规模猜测,N <= 5 * 10^4, K <= 8 * 10^4, 如果路线间几乎没有交点,那么就最多有大约4 * 10^9这么多条边了。结果其实K的总和<=5*10^5,不用考虑那么多路。如果按照

    路线1:A->B->C, 路线2: D->E->F->G这样建立边确实就要N * K条 <= 4 * 10^9这么多了。并且这样好像也没什么用。反而,我们设路线1为S1 和 所有跟S1相连的边, S1-A, S1-B, S1-C… 建好图以后我们就直接求得最短路径, 在二部图里,换乘次数的结果可以推算出来。

    建图中N个路线标号为0-N-1, 其余的标号为N - (N + nodem)。nodem为车站节点总数。

    代码:

    #include<iostream>
    #include<queue>
    #include<string.h>
    #include<map>
    #include<vector>
    #include<stdio.h>
    using namespace std;
    #define INF 2e9
    struct Edge {
        int v, w;
        bool operator<(const Edge a)const {
            return this->w > a.w;
        }
        Edge(int _v, int _w):v(_v), w(_w) {}
    };
    #define MAXN 500100
    int dis[MAXN];
    int N;
    int nodem = 0;
    int shortest(int st, int ed, vector<Edge> G[]) {
        priority_queue<Edge, vector<Edge> > q;
        if (G[st].size() == 0) return -1;
        for (int i = 0; i < nodem; i++) {
            dis[i] = INF;
        }
        dis[st] = 0;
        q.push(Edge(st, 0));
        int u;
        while (!q.empty()) {
            Edge front = q.top();
            q.pop();
            // printf("the front is %d
    ", front.v);
            u = front.v;
            int size = G[u].size();
            for (int i = 0; i < size; i++) {
                Edge e = G[u][i];
                int v = e.v;
                if (G[u][i].w + dis[u] < dis[v]) {
                    dis[v] = G[u][i].w + dis[u];
                    // printf("relax %d... d=%d
    ", v, dis[v]);
                    q.push(Edge(v, dis[v]));
                }
            }
        }
        // for (int i = 0; i < nodem; i++) {
        //     printf("(%d = %d
    ", i, dis[i]);
        // }
        return dis[ed] / 2 - 1;
    }
    map<int, int> mp;
    int getct(int ct) {
        if (mp.count(ct)) {
            return mp[ct];
        } else {
            int count = mp.size() + N;
            mp[ct] = count;
            return mp[ct];
        }
    }
    int main() {
        int M;
        int st, ed;
        ios::sync_with_stdio(false);
        while (cin >> N >> st >> ed) {
            mp.clear();
            int od1, od2, k;
            vector<int>* vc = new vector<int>[N];
            for (int i = 0; i < N; i++) {
                // k stations
                cin >> k;
                for (int j = 0; j < k; j++) {
                    cin >> od1;
                    od1 = getct(od1);
                    vc[i].push_back(od1);
                }
            }
            nodem = N + mp.size();
            // for (map<int, int>::iterator it = mp.begin(); it != mp.end(); ++it) {
            //     cout << it->first << " " << it->second << endl;
            // }
            vector<Edge>* G = new vector<Edge>[nodem];
            nodem = mp.size() + N;
            for (int k = 0; k < N; k++) {
                for (int i = 0; i < vc[k].size(); i++) {
                    od1 = vc[k][i];
                    G[k].push_back(Edge(od1, 1));
                    G[od1].push_back(Edge(k, 1));
                }
            }
            if (st == ed) {
                cout << "0
    ";
                continue;
            }
            int k1, k2;
            k1 = getct(st), k2 = getct(ed);
            cout << shortest(k1, k2, G) << endl;
        }
        return 0;
    }

    测试:

    同一条路线:

    基本样例:

    结果:

  • 相关阅读:
    jQuery中获取元素的属性方法attr()简单用法
    【经验】angularjs 实现带查找筛选功能的select下拉框
    【经验】Angularjs 中使用 layDate 日期控件
    在 VPS 上一键安装KMS服务脚本
    Windows 使用 TCPing 工具来获取 TCP延迟、端口通顺情况、已禁Ping服务器的延迟
    Linux 初级教程:初步进入 Linux 世界
    Debian/Ubuntu TCP拥塞控制技术 ——TCP-BBR 一键安装脚本
    Linux 下 iptables 配置详解
    在 Ubuntu 上安装 LaTeX
    代码审计学习之反射型XSS
  • 原文地址:https://www.cnblogs.com/wangzming/p/7900214.html
Copyright © 2011-2022 走看看