zoukankan      html  css  js  c++  java
  • 题解【POJ3463】Sightseeing

    题面

    题意简述:

    求最短路和比最短路大 (1) 的路径条数。

    考虑在 Dijkstra 算法时同时求出最短路和次短路,以及它们的条数。

    于是我们改变一下堆中存储的数据,多存储一下这个点的类型(最短路或次短路)。

    然后在枚举点的时候分类讨论一下就好了。

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int N = 1003, M = 10003;
    
    int n, m, t;
    int tot, head[N], ver[M], nxt[M], edge[M];
    int S, T;
    int dist[N][2], cnt[N][2];
    bool vis[N][2];
    
    struct Node
    {
        int ver, ty, dis; //点的编号、类型(1 为次短路,0 为最短路) 和 从 1 到当前点的距离
        bool operator > (const Node &a) const
        {
            return dis > a.dis; //重载运算符
        }
    } ;
    
    inline void add(int u, int v, int w)
    {
        ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
    }
    
    inline int Dij()
    {
        memset(cnt, 0, sizeof cnt);
        memset(dist, 0x3f, sizeof dist);
        memset(vis, false, sizeof vis);
        dist[S][0] = 0, cnt[S][0] = 1; //初始化时只有最短路
        priority_queue <Node, vector <Node>, greater <Node> > q;
        q.push((Node){S, 0, 0});
        while (!q.empty())
        {
            Node t = q.top(); q.pop();
            int u = t.ver, ty = t.ty, dis = t.dis, cntu = cnt[u][ty];
            if (vis[u][ty]) continue;
            vis[u][ty] = true;
            for (int i = head[u]; i; i = nxt[i])
            {
                int v = ver[i], w = edge[i];
                if (dist[v][0] == dis + w) cnt[v][0] += cntu; //与最短路长度相同
                else if (dist[v][0] > dis + w) //比最短路还短
                {
                    dist[v][1] = dist[v][0], cnt[v][1] = cnt[v][0]; //先更新次短路为当前的最短路
                    q.push((Node){v, 1, dist[v][1]}); //放入堆中
                    dist[v][0] = dis + w, cnt[v][0] = cntu; //更新最短路
                    q.push((Node){v, 0, dist[v][0]}); //将最短路放入堆中
                }
                else if (dist[v][1] == dis + w) cnt[v][1] += cntu; //与次短路长度相同
                else if (dist[v][1] > dis + w) //比次短路短
                {
                    dist[v][1] = dis + w, cnt[v][1] = cntu;
                    q.push((Node){v, 1, dist[v][1]});
                }
            }
        }
        int ans = cnt[T][0];
        if (dist[T][0] + 1 == dist[T][1]) //存在比最短路长度多 1 的次短路
            ans += cnt[T][1];
        return ans;
    }
    
    int main()
    {
        cin >> t;
        while (t--)
        {
            memset(head, 0, sizeof head);
            tot = 0;
            cin >> n >> m;
            for (int i = 1; i <= m; i+=1)
            {
                int u, v, w;
                cin >> u >> v >> w;
                add(u, v, w); //注意是单向边
            }
            cin >> S >> T;
            cout << Dij() << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    学习python -- 第013天 类与对象
    学习python -- 第013天 bug
    学习python -- 第012天 函数(二)
    学习python -- 第012天 函数(一)
    学习python -- 第011天 字符串
    学习python -- 第010天 列表、元组、字典、集合总结
    排序_快速排序
    链表_逆置
    约瑟夫环-链表
    双栈_队列
  • 原文地址:https://www.cnblogs.com/xsl19/p/12389994.html
Copyright © 2011-2022 走看看