AcWing383 观光(最短路+拓扑序)

这题和最短路计数差不多,只是多了个次短路判断,其实也是跟最短路一样是满足拓扑序的,也就是说不可能出队之后绕一个环回来次短路还变化了

因此也可以用迪杰斯特拉这种天然满足拓扑序的进行更新,只不过需要注意一下最短路和次短路的变化

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+10;
int n,m;
int h[N],ne[N],e[N],idx,w[N];
int dis[N][2];
int cnt[N][2];
int st[N][2];
void add(int a,int b,int c){
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
struct node{
    int d,type,id;
    bool operator > (const node &t) const{
        return d>t.d;
    }
};
void dij(int S){
    memset(dis,0x3f,sizeof dis);
    memset(st,0,sizeof st);
    memset(cnt,0,sizeof cnt);
    priority_queue<node,vector<node>,greater<node> > q;
    dis[S][0]=0;
    cnt[S][0]=1;
    q.push({0,0,S});
    while(q.size()){
        auto t=q.top();
        q.pop();
        int ver=t.id;
        int sign=t.type;
        if(st[ver][sign])
        continue;
        st[ver][sign]=1;
        int i;
        for(i=h[ver];i!=-1;i=ne[i]){
            int j=e[i];
            if(dis[j][0]>dis[ver][sign]+w[i]){
                dis[j][1]=dis[j][0],cnt[j][1]=cnt[j][0];
                q.push({dis[j][1],1,j});
                dis[j][0]=dis[ver][sign]+w[i];
                cnt[j][0]=cnt[ver][sign];
                q.push({dis[j][0],0,j});
            }
            else if(dis[j][0]==dis[ver][sign]+w[i]){
                cnt[j][0]+=cnt[ver][sign];
            }
            else if(dis[j][1]>dis[ver][sign]+w[i]){
                dis[j][1]=dis[ver][sign]+w[i];
                cnt[j][1]=cnt[ver][sign];
                q.push({dis[j][1],1,j});
            }
            else if(dis[j][1]==dis[ver][sign]+w[i]){
                cnt[j][1]+=cnt[ver][sign];
            }
        }
    }
}
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m;
        int i;
        memset(h,-1,sizeof h);
        idx=0;
        for(i=1;i<=m;i++){
            int a,b,c;
            cin>>a>>b>>c;
            add(a,b,c);
        }
        int S,T;
        cin>>S>>T;
        dij(S);
        int ans=cnt[T][0];
        if(dis[T][0]==dis[T][1]-1)
        ans+=cnt[T][1];
        cout<<ans<<endl;
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12827724.html