LOJ10077
题目描述
给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1∼N。问从顶点 1 开始,到其他每个点的最短路有几条。
输入格式
第一行包含 2 个正整数 N,M,为图的顶点数与边数。
接下来 M行,每行两个正整数 x,y,表示有一条顶点 x 连向顶点 y 的边,请注意可能有自环与重边。
输出格式
输出 N 行,每行一个非负整数,第 i 行输出从顶点 1 到顶点 i 有多少条不同的最短路,由于答案有可能会很大,你只需要输出 mod100003 后的结果即可。如果无法到达顶点 i则输出 0。
样例
样例输入
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
样例输出
1
1
1
2
4
样例解释
1 到 5 的最短路有 4 条,分别为 2 条 1→2→4→5 和 2 条 1→3→4→5(由于 4→5 的边有 2 条)。
数据范围与提示
对于 20% 的数据,N≤100;
对于 60% 的数据,N≤1000;
对于 100% 的数据,1≤N≤100000,0≤M≤200000。
-------------------------------------------------------------------------------------------------------------------------
dij求最短路,增加数组cs[ ],用于统计对应点的最短路径条数。
如果刚计算出最短路,则 cs[v]=cs[u]。
如果最短路已经计算出切新计算的最短路与之相同,那么 cs[v]+=cs[u];
注意记得取模。
-------------------------------------------------------------------------------------------------------------------------
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+10; 5 const int maxm=2e5+10; 6 int n,m; 7 struct edge 8 { 9 int u,v,w,nxt; 10 }e[maxm<<1]; 11 int head[maxn],js; 12 void addage(int u,int v) 13 { 14 e[++js].u=u;e[js].v=v;e[js].w=1; 15 e[js].nxt=head[u];head[u]=js; 16 } 17 ll dis[maxn],cs[maxn]; 18 bool vis[maxn]; 19 struct node 20 { 21 int p,dis; 22 bool operator < (node b)const 23 { 24 return dis>b.dis; 25 } 26 }; 27 void dij(int x) 28 { 29 memset(dis,0x3f,sizeof dis); 30 memset(cs,0,sizeof cs); 31 dis[x]=0;cs[x]=1; 32 priority_queue<node>q; 33 q.push((node){x,0}); 34 while(!q.empty()) 35 { 36 node t=q.top(); 37 q.pop(); 38 int u=t.p,d=t.dis; 39 if(vis[u])continue; 40 vis[u]=1; 41 for(int i=head[u];i;i=e[i].nxt) 42 { 43 int v=e[i].v; 44 if(dis[v]>dis[u]+e[i].w) 45 { 46 dis[v]=dis[u]+e[i].w; 47 cs[v]=cs[u]; 48 q.push((node){v,dis[v]}); 49 } 50 else if(dis[v]==dis[u]+e[i].w) cs[v]=(cs[v]+cs[u])%100003; 51 } 52 } 53 } 54 int main() 55 { 56 scanf("%d%d",&n,&m); 57 for(int u,v,i=0;i<m;++i) 58 { 59 scanf("%d%d",&u,&v); 60 addage(u,v);addage(v,u); 61 } 62 dij(1); 63 for(int i=1;i<=n;++i)printf("%lld\n",cs[i]); 64 return 0; 65 }