C. 最短路计数(shortest) [ Problem 4453 ] [ Discussion ]
Description
给出一个N个顶点MM条边的**无向无权图**,顶点编号为1∼N。问从顶点1开始,到其他每个点的最短路有几条。
Input
第一行包含2个正整数N,M,为图的顶点数与边数。
接下来M行,每行两个正整数x,y,表示有一条顶点x连向顶点y的边,**请注意可能有自环与重边**。
Output
包括NN行,每行一个**非负整数**,第i行输出**从顶点1到顶点ii有多少条不同的最短路**,由于答案有可能会很大,你只需要输出**mod 100003**后的结果即可。如果无法到达顶点ii则输出0。
Samples
Hint
样例解释:1到5的最短路有4条,分别为2条1-2-4-5和2条1-3-4-5(由于4-5的边有2条)。
数据说明:
- 对于20%的数据,N≤100;
- 对于60%的数据,N≤1000;
- 对于100%的数据,N≤100000N≤100000,。
Source
石光中学 2018泉州集训普及组day5最短路计数
#pragma GCC optimize(1) #pragma GCC optimize(2) #pragma GCC optimize(3,"Ofast","inline") #include<cstring> #include<cstdio> #include<iostream> #include<queue> #include<algorithm> using namespace std; typedef long long ll; template <typename Tp> void read(Tp &x){//read(n); x=0;char ch=1;int fh; while(ch!='-'&&(ch>'9'||ch<'0')){ ch=getchar(); } if(ch=='-'){ fh=-1;ch=getchar(); }else fh=1; while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+ch-'0';ch=getchar(); } x*=fh; } inline char read1()//字符串读入挂 { register char ch=getchar(); while(ch<'A'||ch>'M')ch=getchar(); return ch; } const int maxn=1e6+100; const int mod=100003; int head[maxn],d[maxn],ans[maxn]; int vis[maxn]; int n,m,s,t,W; struct node{ int to; int next; int w; }edge[maxn]; int cnt=0; void add(int u,int v,int w){ edge[++cnt].w=w; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; } void spfa(){ memset(d,0x3f3f3f,sizeof d); queue<int>q; d[s]=0;//起点 vis[s]=1; ans[s]=1;// 本身为1个最短路 q.push(s); while(q.size()){ int x=q.front();q.pop(); vis[x]=0; for(int i=head[x];i;i=edge[i].next){ int y=edge[i].to; if(d[y]>d[x]+edge[i].w){//如果满足u到v的距离比原本到v的距离小,则更新 d[y]=d[x]+edge[i].w; ans[y]=ans[x];// x点和y点在一条路上,所以y的最短路个数等于x的最短路个数 if(!vis[y]){ q.push(y); vis[y]=1; } } else if(d[y]==d[x]+edge[i].w){ ans[y]+=ans[x];// 该点最短路个数为y最短路个数+x最短路个数 ans[y]%=mod; } } } } void inint(){ cin>>n>>m; s=1;//起点 for(int i=1;i<=m;i++){ int a,b; read(a),read(b); add(a,b,1); add(b,a,1); } } int main(){ inint(); spfa(); for(int i=1;i<=n;i++){ cout<<ans[i]<<endl; } }