HDU 3191 How Many Paths Are There(含0权边的次短路计数)

题目传送门

题目大意

\(DAG\)的次短路长度及次短路条数\((3\leq n\leq 50)\)顶点从\(0\)开始标号

Solution

次短路计数模板题

但有个坑点是存在\(0\)权边,比如边\(A-B\)的边权为\(0\),那么\(A\)必须在\(B\)出堆之前出堆,这样可以保证用\(B\)来松弛其他点时,\(A\)的贡献已经计算在内。

所以先进行拓扑排序

在优先队列中当节点距离相同时比较其拓扑序即可。

一定要注意顶点是从\(0\)开始标号的\(!!!\)

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int head[55],to[5005],nxt[5005],w[5005],cnt=0;//数组要开够 
int in[55],dfn[55];
int n,m,s,t;
int d[55][2],vis[55][2],num[55][2];
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?1:(d==a.d?dfn[x]>dfn[a.x]:0);//距离相同时比较拓扑序 
    }
};
void add(int u,int v,int ww){
    nxt[++cnt]=head[u];
    to[cnt]=v;
    w[cnt]=ww;
    head[u]=cnt;
}
void topo(){
    int cnt2=0;
    queue<int>q;
    memset(dfn,0,sizeof(dfn));
    for(int i=0;i<n;++i){//顶点是从0开始标号的 
        if(!in[i]){
            dfn[i]=++cnt2;
            q.push(i);
        }
    }
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=nxt[i]){
            int v=to[i];
            in[v]--;
            if(!in[v]){
                dfn[v]=++cnt2;
                q.push(v);
            }
        }
    }
}
void 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],temp=d[u][flag]+w[i];
            if(d[v][0]>temp){
                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[v][0]=temp;
                num[v][0]=num[u][flag];
                q.push(node(d[v][0],v,0));
            }else if(d[v][0]==temp){
                num[v][0]+=num[u][flag];
            }else if(d[v][1]>temp){
                d[v][1]=temp;
                num[v][1]=num[u][flag];
                q.push(node(d[v][1],v,1));
            }else if(d[v][1]==temp){
                num[v][1]+=num[u][flag];
            }
        }
    }
}
int main(){
    int u,v,ww;
    while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF){
        cnt=0;//cnt记得重置为0 
        memset(head,-1,sizeof(head));
        memset(in,0,sizeof(in));
        for(int i=1;i<=m;++i){
            scanf("%d%d%d",&u,&v,&ww);
            add(u,v,ww);
            in[v]++;
        }
        topo();
        dij(s,t);
        printf("%d %d\n",d[t][1],num[t][1]);
    }
    return 0;
}

posted @ 2021-01-21 22:19  lzc2001  阅读(64)  评论(0)    收藏  举报