「LuoguP1144」 最短路计数(dijkstra
题目描述
给出一个NN个顶点MM条边的无向无权图,顶点编号为1-N1−N。问从顶点11开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:
第一行包含22个正整数N,MN,M,为图的顶点数与边数。
接下来MM行,每行22个正整数x,yx,y,表示有一条顶点xx连向顶点yy的边,请注意可能有自环与重边。
输出格式:
共NN行,每行一个非负整数,第ii行输出从顶点11到顶点ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans \bmod 100003ansmod100003后的结果即可。如果无法到达顶点ii则输出00。
输入输出样例
说明
11到55的最短路有44条,分别为22条1-2-4-51−2−4−5和22条1-3-4-51−3−4−5(由于4-54−5的边有22条)。
对于20\%20%的数据,N ≤ 100N≤100;
对于60\%60%的数据,N ≤ 1000N≤1000;
对于100\%100%的数据,N<=1000000,M<=2000000N<=1000000,M<=2000000。
题解
算是最短路的小技巧?
if(dis[to]>dis[x]+1)ans[to]=ans[x]; else if(dis[to]==dis[x]+1)ans[to]+=ans[x];
在dijkstra的同时顺便维护,这样就可以了。
不是很敢用spfa。
然后注意一下这道题是无向图要建双向边就好了。
1 /* 2 qwerta 3 P1144 最短路计数 Accepted 4 100 5 代码 C++,1.05KB 6 提交时间 2018-11-05 22:20:55 7 耗时/内存 247ms, 9120KB 8 */ 9 #include<iostream> 10 #include<cstring> 11 #include<cstdio> 12 #include<queue> 13 using namespace std; 14 struct emm{ 15 int e,f; 16 }a[4000003]; 17 int h[1000003]; 18 int tot=0; 19 void con(int x,int y) 20 { 21 a[++tot].f=h[x]; 22 h[x]=tot; 23 a[tot].e=y; 24 a[++tot].f=h[y]; 25 h[y]=tot; 26 a[tot].e=x; 27 return; 28 } 29 int d[1000003]; 30 int s[1000003]; 31 struct ahh{ 32 int nod,v; 33 }; 34 struct cmp{ 35 bool operator()(ahh qaq,ahh qwq){ 36 return qaq.v>qwq.v; 37 }; 38 }; 39 priority_queue<ahh,vector<ahh>,cmp>q; 40 bool sf[1000003]; 41 const int mod=100003; 42 int main() 43 { 44 int n,m; 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=m;++i) 47 { 48 int x,y; 49 scanf("%d%d",&x,&y); 50 con(x,y); 51 } 52 memset(d,127,sizeof(d)); 53 d[1]=0;s[1]=1; 54 q.push((ahh){1,0}); 55 while(!q.empty()) 56 { 57 int x; 58 do{x=q.top().nod;q.pop();}while(sf[x]&&!q.empty()); 59 sf[x]=1; 60 for(int i=h[x];i;i=a[i].f) 61 if(!sf[a[i].e]) 62 { 63 if(d[a[i].e]>d[x]+1) 64 { 65 d[a[i].e]=d[x]+1; 66 s[a[i].e]=s[x]; 67 q.push((ahh){a[i].e,d[a[i].e]}); 68 } 69 else if(d[a[i].e]==d[x]+1) 70 { 71 s[a[i].e]+=s[x]; 72 s[a[i].e]%=mod; 73 } 74 } 75 } 76 for(int i=1;i<=n;++i) 77 printf("%d\n",s[i]%mod); 78 return 0; 79 }