首页 > 其他分享 >次短路

次短路

时间:2024-03-09 10:13:25浏览次数:34  
标签:node cnt dist int 短路 ne

题目链接

思路:拆点

将一个节点 \(node\) 拆为 \(node[0]\) 和 \(node[1]\),其中 \(node[0]\) 是 \(node\) 的最短路,\(node[1]\) 是 \(node\) 的次短路,如果不拆点的话,那么每个 \(node\) 只会出队更新其他节点一次(即st[node]=true;此时 \(node\) 要么是满足最短路要么满足次短路),然而事实是,次短路和最短路都可能用来更新其他节点,因此我们需要st[node][0]=true;/st[node][1]=true;

在 \(dijkstra\) 和 \(dfs\) 中次短路也满足拓扑序,因此我们可以用 \(dijkstra\) 来求解权值不为 \(1\) 的问题,注意不能直接用 \(spfa\),因为 \(spfa\) 不满足拓扑序,除非我们先用 \(top_sort\) 预处理,但那样太麻烦。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int N = 1010, M = 10010;

typedef struct ver_t {
    // type=0 --> 最短路
    // type=1 --> 次短路 
    int distance, ver, type;    
    bool operator<(const ver_t &x) const {
        return distance > x.distance;
    }
} Ver;

int n, m, head, tail;
int h[N], e[M], ne[M], w[M], idx;
int dist[N][2], cnt[N][2];
bool st[N][2];

void add(int a, int b, int c)
{
    w[idx] = c;
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

int dijkstra()
{
    // 0 --> 最短路
    // 1 --> 次短路
    memset(dist, 0x3f, sizeof dist);
    memset(cnt, 0, sizeof cnt);
    memset(st, false, sizeof st);
    dist[head][0] = 0;
    cnt[head][0] = 1;

    priority_queue<Ver> q;
    q.push({dist[head][0], head, 0});
    while(q.size())
    {
        auto [distance, ver, type] = q.top();
        q.pop();
        if(st[ver][type])   continue;
        st[ver][type] = true;
        for(int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            /*小 -------------------------------------> 大
                    dist[j][0]          dist[j][1]
            ne_dist ne_dist    ne_dist  ne_dist     (四种情况)*/
            int ne_dist = distance + w[i];
            if(ne_dist < dist[j][0])    // 比最短路还要小
            {
                dist[j][1] = dist[j][0];
                cnt[j][1] = cnt[j][0];
                dist[j][0] = ne_dist;
                cnt[j][0] = cnt[ver][type];
                q.push({dist[j][0], j, 0});
                q.push({dist[j][1], j, 1});
            }
            else if(ne_dist == dist[j][0])  // 和最短路一样长
                cnt[j][0] += cnt[ver][type];
            else if(ne_dist < dist[j][1])   // 比次短路长
            {
                dist[j][1] = ne_dist;
                cnt[j][1] = cnt[ver][type];
                q.push({dist[j][1], j, 1});
            }
            else if(ne_dist == dist[j][1])  // 和次短路一样长
                cnt[j][1] += cnt[ver][type];
        }
    }
    return cnt[tail][0] + cnt[tail][1] * (dist[tail][1] == dist[tail][0] + 1);
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int T;  cin >> T;
    while(T -- )
    {
        memset(h, -1, sizeof h), idx = 0;
        cin >> n >> m;
        while(m -- )
        {
            int a, b, c;   cin >> a >> b >> c;
            add(a, b, c);
        }
        cin >> head >> tail;
        cout << dijkstra() << endl;
    }
    return 0;
}

标签:node,cnt,dist,int,短路,ne
From: https://www.cnblogs.com/ALaterStart/p/18062296

相关文章

  • ACwing 最短路算法
    ACwing最短路算法首先介绍一下各个最短路算法的分类及适用情况注意:SPFA算法在部分情况下会被卡一些特殊数据,当被卡时,换用其他对应的算法;下面依次介绍:朴素版dijkstra算法朴素版dijkstra算法适用于稠密图,所以我们只以稠密图的存图方式去介绍;核心思想:首先我们定义一个集合st......
  • abc325E 火车+班车的最短路
    题面:有n座城市,从城市i到城市j可以坐班车,需要A*D[i][j]时间,也可以坐火车,需要B*D[i][j]+C时间。可以从班车换到火车,但反过来不行。换乘时间不计,求从城市1到城市n的最短时间。范围:n<1000;A,B,C<1E6;D[i]][j]<1E6并且D[i][i]=0。思路:先预处理出任意两城市之间的耗时,包括班车D[i][j......
  • 最短路径算法
    最短路径我们把边具有权重的图称为带权图,权重可以理解为两点间的距离。一个图中任意两点会有多条路径联通,最短路径就是这些路径中最短的一条。负环:环中所有边权之重和小于0的环Floyed算法算法思想如何让两个点(假设a到b)的距离变短,只能引入第三个点k,通过k进行中转即a->k->b,当......
  • 最短路径问题的Dijastra算法
    求节点间最短路径的Dijastra算法思路概述给定一个权值非负的有向连通图,求某个特定原点(假定节点编号为0)到终点的最短路径权值之和。Dijastra算法采用贪心思想,每次选取最短距离可到达的点确定对应路径权值之和,并用以更新其它邻接点的可到达最短距离直至确定终点或者所有节......
  • leetcode--1976. 到达目的地的方案数(最短路)
    记录12:052024-3-5https://leetcode.cn/problems/number-of-ways-to-arrive-at-destination/通过最短路找到从源点到目标点距离,在更新的过程中,对某个点记录下可以达到最短距离的父亲节点,然后从目标点往回dp就可以了(有种逆向拓扑排序的感觉)当然这是不必要的,在更新最短距离的......
  • 最短路算法模版集合
    例题https://www.luogu.com.cn/problem/P1339朴素dijkstra(邻接表)dijkstra正确性来自于贪心也就是st数组内的数(dist)必须逐渐变大这样才能保证后面的数更新的时候,当前的第三边dist[t]都是最小值[详见](https://www.acwing.com/solution/content/94237/)dist[x]表示x......
  • 最短路
    1算法描述在一图中,从一点出发,沿图的边走到另一点所经过的路径中,各边上权值和最小的路径,叫做最短路径。最短路算法就是求解最短路径问题的算法。其中,单源最短路径指从图中某一点到另外所有点的最短路径;多源最短路径指从图中每一点到另外所有点的最短路径。2四大最短路算法2.1......
  • && 短路效果测试
    C#:staticvoidMain(string[]args){boolresult=true;result&=Func();result&=Func();result&=Func();Console.WriteLine("&=最后结果:{0}\n",result);Console.ReadKey();result=result......
  • SPFA最短路
    目录从Bellman-Ford开始核心思想模拟算法执行过程时间复杂度模板spfaspfa优化的思想模板从Bellman-Ford开始对于所有边权都大于等于0的图,任意两个顶点之间的最短路,显然不会经过重复的顶点或者边。也就是说任意一条最短路经过的定点数不会超过n个,边不会超过n-1条边而对于有边权......
  • 分层图最短路
    分层最短路用更加具体或者形象一点的说法就是有限制的最短路径问题。通常是拆点解决问题,原图中的点加上一个当前点的状态,成为一个新的点P4568[JLOI2011]飞行路线P4568[JLOI2011]飞行路线#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=......