• 暑假练习:上学


    个人笔记,仅供复习

    上学
    【题意描述】
    小喵喵家附近有n个路口,m条道路连接着这些路口,而且通过这些道路各自需要一些时间c[i]。小喵喵在1号路口,他要去n号路口上学,但是他马上要迟到了,所以他想知道最短需要多长时间能够到达学校。其中忽略小喵喵由于出家门、到n号路口之后进入学校、从一条道路移动到另一条道路之类的时间,只计算他在这些道路上花费的时间总和。
    除此之外,小喵喵还有k个时间暂停器,每个可以使某一条道路的经过时间变为0.
    【输入格式】
    第1行三个整数n,m,k,表示路口个数,道路的数量,时间暂停器的数量。
    第2~m+1行每行三个整数u[i],v[i],c[i],表示u[i]和v[i]之间有一条可以双向通行的道路,通过所需时间为c[i]。
    【输出格式】
    一个整数,表示小喵喵所需的最短时间。
    【样例输入输出】
    5 6 1
    1 2 2
    1 3 4
    2 4 3
    3 4 1
    3 5 6
    4 5 2 3
    【样例解释】
    小喵喵选择从1->3->4->5,并且在1->3的道路上使用时间暂停器。
    总耗时为0+1+2=3.
    【数据范围】
    对于20%的数据,n<=5,m<=10.
    对于另外20%的数据,k=0.
    对于另外30%的数据,k=1.
    对于所有的数据,n<=1000,m<=10000,k<=10,c[i]<=109,保证存在从1号路口到n号路口的路径。注意,可能存在两条道路的起点和终点组成的集合相同,也可能存在起点和终点是相同路口的道路。

    解题思路:如果没有c[i]的话,这题毫无疑问就是典型的图论中求最短路的问题,但是他可以任意选几段路使时间为0,这样的话就没办法用一层图来解决。我们可以考虑建立k层图,不同层间的路径权值为0,其中跨图走为单向,即一旦走到下层图,就不能再返回上层图,这样就保证了只使用k次时间暂停器。

    解题代码:(来自老师)

    #include <iostream>
    #include <queue>
    using namespace std;
    struct Node{
        int v, w;
        Node(){}
        Node(int av, int aw): v(av), w(aw){}
        bool operator < (const Node& b) const {
            return w > b.w;
        }
    }node;
    vector<vector<Node> > g;
    queue<Node> q;
    vector<long long> dist, uptimes;
    const long long INF = (long long)1 << 62;
    int n, m, k, u, v, w;
    bool spfa() {
        q.push(Node(1+k*n, 0)); dist[1+k*n] = 0;
        while (q.size()) {
            node = q.front(), q.pop();
            for (int i = 0, j = g[node.v].size(); i < j; ++i) {
                Node tN = g[node.v][i];
                if (dist[tN.v] > dist[node.v] + tN.w) {
                    dist[tN.v] = dist[node.v] + tN.w, q.push(Node(tN.v, node.w+tN.w));
                    if(++uptimes[tN.v] >= n) return false;
                }
            }
        }
        return true;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin >> n >> m >> k;
        g.resize(m*(k+2)); dist.resize(m*(k+2)); uptimes.resize(m*(k+2));
        fill(dist.begin(), dist.end(), INF);
        for (int i = 1; i <= m; ++i) {
            cin >> u >> v >> w;
            //使用多层图,将动态规划的各个状态以不同层列出,0边在不同层之间连接,从而避免了重边
            for (int j = 0; j <= k; ++j) {
                g[u+j*n].push_back(Node(v+j*n, w));
                g[v+j*n].push_back(Node(u+j*n, w));
                if (j) {
                    g[u+j*n].push_back(Node(v+(j-1)*n, 0));
                    g[v+j*n].push_back(Node(u+(j-1)*n, 0));
                }
            }
        }
        spfa();
        long long minN = INF;
        for (int i = 0; i <= k; ++i)
            minN = min(minN, dist[n+i*n]);
        cout << minN << endl;
        return 0;
    }
  • 相关阅读:
    MaxScale智能读写
    flask简单demo
    django简单demo
    git原生私服之git&gitweb
    gerrit 解决中文乱码相关配置(转载)
    gerrit集成gitweb:Error injecting constructor, java.io.IOException: Permission denied
    gerrit: Error in POST /accounts/self/preferences
    redmine 配置邮件发送为async后,不能发送邮件(转载)
    gerrit error: unpack failed: error Permission denied
    centos修改hostname以及时间同步
  • 原文地址:https://www.cnblogs.com/long98/p/10352226.html
Copyright © 2020-2023  润新知