洛谷P1144 最短路计数(dijkstra)

题目传送门

题目大意

分别求出点\(1\)到点\(1\)~\(i\)的最短路条数(边权为1,输入包括重边和自环)

Solution

最短路计数模板题

因为边权为1,所以其实可以用BFS求最短路。

这里我还是用dijkstra,适用于任意正权图。

自环跳过不建边,因为最短路肯定不会经过自环边。

重边正常建图即可。

#include<bits/stdc++.h>
using namespace std;
#define maxn1 1000005
#define maxn2 4000005
#define INF 0x3f3f3f3f
#define MOD 100003
int n,m;
int head[maxn1],nxt[maxn2],to[maxn2],cnt=0;
int d[maxn1],vis[maxn1],num[maxn1];
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;
}
struct node{
    int d,x;
    node(int d,int x):d(d),x(x){}
    bool operator < (const node& a)const{
        return d>a.d;
    }
};
void add(int u,int v){
    nxt[++cnt]=head[u];
    to[cnt]=v;
    head[u]=cnt;
}
void dij(int s,int t){
    d[s]=0;
    num[s]=1;
    priority_queue<node>q;
    q.push(node(0,1));
    while(!q.empty()){
        node u=q.top();q.pop();
        if(vis[u.x])continue;
        vis[u.x]=1;
        for(int i=head[u.x];i!=-1;i=nxt[i]){
            int v=to[i];
            if(d[v]>d[u.x]+1){//关键点1 
                d[v]=d[u.x]+1;
                num[v]=num[u.x];
                q.push(node(d[v],v));
            }
            else if(d[v]==d[u.x]+1){//关键点2 
                num[v]=(num[v]+num[u.x])%MOD;
            }
        }
    }
}
int main(){
    read(n),read(m);
    int u,v;
    memset(head,-1,sizeof(head));
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    memset(d,INF,sizeof(d));
    for(int i=1;i<=m;++i){
        read(u),read(v);
        if(u==v)continue;
        add(u,v);
        add(v,u);
    }
    dij(1,n);
    for(int i=1;i<=n;++i){
        printf("%d\n",num[i]);
    }
    return 0;
}
posted @ 2021-01-20 14:46  lzc2001  阅读(50)  评论(0)    收藏  举报