对题解“最短路径条数”的补充说明
查看原帖
对题解“最短路径条数”的补充说明
120868
dbxxx楼主2023/4/18 20:13

这里以第一篇题解为例补充说明。

第一篇题解代码里求的那个东西,也就是:

			if(dis[v]==dis[u]+e[i].w) cnt[v]++;
			if(dis[v]>dis[u]+e[i].w){
				dis[v]=dis[u]+e[i].w;
				cnt[v]=1;
				q.push(make_pair(dis[v],v));
			}

实际上 cnt[u] 并不是 11 到 uu 的最短路径数量,而是满足 1⇝v→u1 \rightsquigarrow v \to u 为一条最短路径的点 vv 的数量。上面这个路径 1⇝v1 \rightsquigarrow v 通过多条边(可以是一条甚至是零条)的路径到达,v→uv \to u 通过一条边直接到达。

如果想要统计 1⇝u1 \rightsquigarrow u 的最短路径数量,正确的写法是这样的。

			if(dis[v]==dis[u]+e[i].w) cnt[v]+=cnt[u];
			if(dis[v]>dis[u]+e[i].w){
				dis[v]=dis[u]+e[i].w;
				cnt[v]=cnt[u];
				q.push(make_pair(dis[v],v));
			}

事实上,最短路径数量和“点 vv 数量”在本题中判断都无问题。

考虑最短路径数量 >1>1 的情况,如果有一条最短路径经过特殊边,那么第二条最短路径肯定是不经过特殊边的,因为这题里边权都是正的,经过一条特殊边之后权值就已经到了最短路,不能再走多余的路了。

而满足 1⇝v→u1 \rightsquigarrow v \to u 为一条最短路径的点 vv 的数量如果 >1> 1,意味着合法的点 vv 除了点 11 以外必然有一个其它点,经过这个点的那条最短路径一定不经过特殊边。

但是,最短路径数量有一个问题:上界可以很大。即使不允许重边,也能构造出这么一个东西:

1⇝41 \rightsquigarrow 4 有两条最短路径,4⇝74 \rightsquigarrow 7 有两条最短路径,7⇝107 \rightsquigarrow 10 有两条最短路径,10⇝1310 \rightsquigarrow 13 有两条最短路径,13⇝1613 \rightsquigarrow 16 有两条最短路径,所以 1⇝161 \rightsquigarrow 16 的最短路径数量是 25=322^5 = 32。

这个增长速度是指数爆炸的,只要我们再接着接下去,大概达到的最短路径数量上界是 2n/32^{n / 3}。如果想要直接统计出这样的数量,高精度是无可避免的。

所以本题直接统计最短路径数量再判断是不太合理的。一种处理方式是采用上面的“点 vv 数量”策略,还有一种处理方式是,我们并不关心最短路径数量的具体值,只关心最短路径数量是否 >2>2,因此等到最短路径数量 =2=2 之后不让它再加下去就可以了。

2023/4/18 20:13
加载中...