对于计数问题,如果对于dp,那么只要一路推过来就好。但是图内可能存在环,因此必须要想办法
我们可以发现是,这些环对答案没有影响,其实最短路的计数和dp的计数如出一辙
都是在拓扑序上进行。因此我们可以在端点往外bfs或者迪杰斯特拉,这样就能产生拓扑树
而答案就是这样更新而来。如果图中有负权,那么用spfa,但是spfa不是天生满足拓扑序,还需要做一些处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=4e5+10; const int mod=100003; int h[N],ne[N],e[N],cnt[N],idx; int dis[N]; int n,m; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void bfs(){ memset(dis,0x3f,sizeof dis); queue<int> q; q.push(1); cnt[1]=1; dis[1]=0; while(q.size()){ int t=q.front(); q.pop(); int i; for(i=h[t];i!=-1;i=ne[i]){ int j=e[i]; if(dis[j]>dis[t]+1){ dis[j]=dis[t]+1; cnt[j]=cnt[t]; q.push(j); } else if(dis[j]==dis[t]+1){ cnt[j]=(cnt[j]+cnt[t])%mod; } } } } int main(){ cin>>n>>m; int i; memset(h,-1,sizeof h); for(i=1;i<=m;i++){ int a,b,c; cin>>a>>b; add(a,b),add(b,a); } bfs(); for(i=1;i<=n;i++){ printf("%d ",cnt[i]); } }