洛谷 P1144 最短路计数 题解
这道题的目的是要求出每个点的单源最短路数量。
那么对于每个点,我们需要知道其距离起点的距离和当前搜到的最短路的条数,分别用数组 dis [ i ] 和 f [ i ] 来表示。
从而,我们选择用广搜来进行实现(一是边权为恒为1,二是保证第一次搜到的 dis [ i ] 即为最短的)
对于每一个新搜到的点,操作为更新距离和更新最短路条数(等于上一个节点的最短路条数,因为是第一次搜到)。
对于每一个搜到过的点,如果其距离等于最短路距离,则将其最短路条数加上上一个节点的最短路条数。
#include#include #include #include #include #define maxn 2000010 #define int long long #define rep(i,s,e) for(register int i=s;i<=e;++i) #define dwn(i,s,e) for(register int i=s;i>=e;--i) using namespace std; inline int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();} return f*x; } inline void write(int x) { if(x<0){putchar('-');x=-x;} if(x>9)write(x/10); putchar(x%10+'0'); } int n,m,cnt; int head[maxn]; int dis[maxn],f[maxn]; struct node { int v,nex; }edge[maxn]; inline void add(int x,int y) { edge[++cnt].v=y; edge[cnt].nex=head[x]; head[x]=cnt; } signed main() { n=read();m=read(); rep(i,1,m) { int x=read(),y=read(); add(x,y); add(y,x); } dis[1]=0;f[1]=1; rep(i,2,n) dis[i]=(1<<30); queue<int> q; q.push(1); while(!q.empty()) { int from=q.front(); q.pop(); for(int i=head[from];i;i=edge[i].nex) { int to=edge[i].v; if(dis[to]==(1<<30)) { dis[to]=dis[from]+1; f[to]=f[from]; q.push(to); } else if(dis[to]==dis[from]+1) f[to]=(f[to]+f[from])%100003; } } rep(i,1,n) cout< endl; return 0; }