P1144 最短路计数

题目描述

给出一个N个顶点M条边的无向无权图,顶点编号为1-N。问从顶点1开始,到其他每个点的最短路有几条。

输入输出格式
输入格式:
第一行包含2个正整数N,M,为图的顶点数与边数。

接下来M行,每行2个正整数x,y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。

输出格式:

共N行,每行一个非负整数,第ii行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans mod 100003后的结果即可。如果无法到达顶点i则输出0。

输入输出样例

输入样例#1:

5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5

输出样例#1:

1
1
1
2
4

【解题思路】:

在dijkstra函数内定义一个node类型的变量,然后每次用这个变量提取队首元素,统计这个点的前驱到这个点的路径是否等于它的最短路径,然后一边算一边模即可。

【AC代码】:

#include<bits/stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define Mod 100003
using namespace std;
inline void read(int &x){
    char ch=getchar(),c=ch;
	x=0;
    while(ch<'0' || ch>'9'){
    	 c=ch;
		 ch=getchar();
	}
    while(ch>='0' && ch<='9'){
    	x=(x<<1)+(x<<3)+ch-'0';
		ch=getchar();
	}
    if(c=='-')x=-x;
} 

int n,m,dis[1000005],head[1000005],s,js[1000005],num;
struct Edge
{
    int v,w,nxt;
}edge[2000005];

inline void ct(int u,int v,int w)
{
    edge[++num].v=v;
    edge[num].w=w;
    edge[num].nxt=head[u];
    head[u]=num;
}
struct node
{
    int x,y;
    bool operator < (const node &a) const
    {
        return y>a.y;
    }
};
void dijkstra(){
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    priority_queue<node>q;
    js[1]=1;
    q.push((node){1,0});
    node a;
    while(!q.empty()){
        a=q.top();
        int u=a.x,d=a.y;                       
        q.pop();
        if(d!=dis[u])continue;
        for(int i=head[u];i;i=edge[i].nxt){
            int v=edge[i].v;
            if(d+edge[i].w==dis[v])js[v]=(js[u]+js[v])%Mod;
            if((dis[v]>dis[u]+edge[i].w)){
                dis[v]=dis[u]+edge[i].w;
                js[v]=js[u];
                q.push((node){v,dis[v]});
            }
        }
    }
}
int main()
{
    read(n),read(m);
    for(int i=1,u,v;i<=m;++i)
    {
        read(u),read(v);
        ct(u,v,1);
        ct(v,u,1);
    }
    dijkstra();
    for(int i=1;i<=n;++i)cout<<js[i]<<'\n';
    cout<<'\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值