HDU 1688 Sightseeing (次短路计数)

题目传送门

题目大意

\(s\)\(t\)的最短路条数加上比最短路大1的路径条数\((1\leq n\leq 10^3,1\leq m\leq 10^4,1\leq L\leq 10^3,0\leq ans\leq10^9)(\)单向边\()\)

Solution

最短路计数与次短路计数的模板题,只要注意判断一下次短路是否正好为最短路\(+1\)即可。

每次取队首元素来松弛最短路和次短路,注意只有松弛最短路失败时才松弛次短路,具体见代码。

注意每次d数组更新都要入队

因为是多组数据,别忘了重置cnt以及其他数组。

#include<bits/stdc++.h>
using namespace std;
#define maxn1 1005
#define maxn2 10005
#define INF 0x3f3f3f3f
int T;
template<typename T>void read(T& x){
    int f=0;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){f|=(ch=='-');ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
    if(f)x=-x;
}
int head[maxn1],to[maxn2],nxt[maxn2],w[maxn2],cnt=0;
void add(int u,int v,int ww){
    nxt[++cnt]=head[u];
    to[cnt]=v;
    w[cnt]=ww;
    head[u]=cnt;
}
struct node{
    int d,x,flag;
    node(int d,int x,int flag):d(d),x(x),flag(flag){}
    bool operator < (const node& a)const{
        return d>a.d;
    }
};
int d[maxn1][2],vis[maxn1][2],num[maxn1][2];
int dij(int s,int t){
    memset(d,INF,sizeof(d));
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    priority_queue<node>q;
    d[s][0]=0;
    num[s][0]=1;
    q.push(node(0,s,0));
    while(!q.empty()){
        int u=q.top().x,flag=q.top().flag;
        q.pop();
        if(vis[u][flag])continue;
        vis[u][flag]=1;
        for(int i=head[u];i!=-1;i=nxt[i]){
            int v=to[i];
            if(d[v][0]>d[u][flag]+w[i]){
                if(d[v][0]!=INF){//一个小优化 
                d[v][1]=d[v][0];
                num[v][1]=num[v][0];
                q.push(node(d[v][1],v,1));//每次d数组更新都要入队 
                }
                d[v][0]=d[u][flag]+w[i];
                num[v][0]=num[u][flag];
                q.push(node(d[v][0],v,0));
            }else if(d[v][0]==d[u][flag]+w[i]){
                num[v][0]+=num[u][flag];
            }else if(d[v][1]>d[u][flag]+w[i]){
                d[v][1]=d[u][flag]+w[i];
                num[v][1]=num[u][flag];
                q.push(node(d[v][1],v,1));
            }else if(d[v][1]==d[u][flag]+w[i]){
                num[v][1]+=num[u][flag];
            }
        }
    }
    int ans=num[t][0];
    if(d[t][1]==d[t][0]+1)
        ans+=num[t][1];
    return ans;
}
int main(){
    read(T);
    int n,m,s,t,u,v,ww;
    while(T--){
        read(n),read(m);
        memset(head,-1,sizeof(head));
        cnt=0; //别忘了重置cnt
        for(int i=1;i<=m;++i){
            read(u),read(v),read(ww);
            add(u,v,ww);
        }
        read(s),read(t);
        printf("%d\n",dij(s,t));
    }
    return 0;
}
posted @ 2021-01-21 17:38  lzc2001  阅读(81)  评论(0)    收藏  举报