题目链接:点击查看
题目大意:给出 n 个点和 m 条边的有向图,每条边的长度为 1 ,有一个属性由 0 或 1 表示,现在需要给每个节点赋值,使得:
- 如果点 u 的权值为 0 ,则 u 只能走 ( u , v ) 且这条边的属性为 0 的边
- 如果点 u 的权值为 1 ,则 u 只能走 ( u , v ) 且这条边的属性为 1 的边
问如何赋值能让点 1 到点 n 的最短路最大,输出一种构造方案
题目分析:首先设计 dp ,为了契合最短路的模板,在这个题目中我用 d 数组作为 dp 数组,d[ i ][ 0 ] 和 d[ i ][ 1 ] 分别表示 i 点为 0 或 1 时,到达点 n 的最短路,显然比较 d[ i ][ 0 ] 和 d[ i ][ 1 ] 的大小,选较大的为点 i 赋值就能让最短路最大了,当两者相等时,赋值为 0 或 1 都是一样的
然后考虑 dp 的转移,因为我们要求以 n 个点为起点的 d[ i ][ 0 ] 和 d[ i ][ 1 ] ,肯定是不能求 n 次迪杰斯特拉的,又因为所有的 d 数组都是以点 n 为终点的,所以我们不妨将整个图翻转,然后求以点 n 为起点的单源最短路
下面说一下该如何转移状态方程,假如现在有一条由 u 向 v 的边,且该边的属性为 t ,因为我们要使得最短路最大,所以显然要用 max( d[ u ][ 0 ] , d[ u ][ 1 ] ) 向点 v 进行转移,这就是最简单的最短路问题了,因为这个题目中的边权都为 1 ,所以我们可以用 bfs 来代替迪杰斯特拉
有一点需要注意的是,因为每个点有两个属性需要更新,所以每个点可能会被遍历多次,如果像普通迪杰斯特拉那样加一个 vis 限制的话,可能会导致答案错误,所以我们换一种方法来约束,在代码实现中会打上注释,其效果与 vis 标记的效果是一样的
最后的答案显然就是 max( d[ 1 ][ 0 ] , d[ 1 ][ 1 ] ) 了,方案的话按照求出来的数组直接构造即可
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include