次短路

次短路:大于最短路的最小路径;

最短路:求法很多,不说了

最短路计数:计算最短路的数量,以dijstra算法解最短路来说,多开一个计数的数组num[N],当我们跟新某一个点时,dis[u]>dis[v]+e[u][v] (u点与v点有路),更新num[u]=num[v];  如果dis[u]=dis[v]+e[u][v],那就单独更新数量:num[u]+=num[v];

次短路算法:在最短路的基础上,次短路可以由次短路+边更新,也可以由最短路+边 跟新,这里注意一点,因为次短路更新时也会对其它次短路产生影响,所以更新次短路时也需要入队,我们先尝试更新最短路,成功的话就把原来的最短路给次短路,不成功的话就单独尝试更新次短路;

次短路数量:和最短路计数差不多,优先更新最短路,最短路更新成功时,次短路的数量就是原来最短路的数量,不成功的话就单独更新次短路,方法和最短路相同,为了知道我们每次取出的点是最短路的还是次短路的,所以有必要在队列里记录一样。

https://www.acwing.com/problem/content/385/

#include<bits/stdc++.h>
using namespace std;

typedef pair<int,int>PII;
const int N=1010,M = 10010;
int n,m,s,f;
int head[N],nextt[M*2],to[M*2],len[M*2],cnt;
int dis[N][2],num[N][2],vis[N][2];

void add(int u,int v,int w){
    to[cnt]=v,len[cnt]=w,nextt[cnt]=head[u],head[u]=cnt++;
}
struct node{
    int to,dis,kind;
    bool operator <(const node a)const{
        return a.dis<dis;
    }
};

void dijstra(){
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    dis[s][0]=0,num[s][0]=1;
    priority_queue<node>q;
    q.push({s,dis[s][0],0});
    while(q.size()){
        int u=q.top().to,ds=q.top().dis,kind=q.top().kind;q.pop();
        if(vis[u][kind])continue;
        vis[u][kind]=1;
         for(int i=head[u];i;i=nextt[i]){
             int v=to[i];
             if(dis[v][0]>dis[u][kind]+len[i]){
                 dis[v][1]=dis[v][0];num[v][1]=num[v][0];
                 q.push({v,dis[v][1],1});
                 dis[v][0]=dis[u][kind]+len[i];
                 num[v][0]=num[u][kind];
                 q.push({v,dis[v][0],0});
             }
             else if(dis[v][0]==dis[u][kind]+len[i]){
                 num[v][0]+=num[u][kind];
             }
             else if(dis[v][1]>dis[u][kind]+len[i]){
                 dis[v][1]=dis[u][kind]+len[i];
                 num[v][1]=num[u][kind];
                 q.push({v,dis[v][1],1});
             }
             else if(dis[v][1]==dis[u][kind]+len[i]){
                 num[v][1]+=num[u][kind];
             }
         }
    }
}

int main(){
    int t; cin>>t;
    while(t--){
        cin>>n>>m;
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1;i<=m;i++){
            int u,v,w;
            cin>>u>>v>>w;
            if(u==v)continue;
            add(u,v,w);
        }
        cin>>s>>f;
        dijstra();
        // cout<<dis[f]<<" "<<dis1[f]<<" \n";
        // cout<<num[f]<<" "<<num1[f]<<" \n";
        cout<<(dis[f][1]==dis[f][0]+1?num[f][1]+num[f][0]:num[f][0])<<endl;
    }
    return 0;
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值