首先建立虚点,然后跑最短路,注意考虑一种特殊情况。
大意
给定 $n$ 个点 $m$ 条边的简单无向图,边有颜色,要求从 $1$ 走到 $n$,但是要求走的每条边 $u\to v$ 都要满足 $u$ 的出边中没有其他与 $(u,v)$ 同色的边。
每条边可以以 $p_i$ 的代价被修改为任意其他的颜色,若想使存在从 $1$ 走到 $n$ 的一个方案,求最小花费。
可能无解。
$n\le 10^5$,$m\le 2\times 10^5$,颜色数 $\le m$,$1\le p_i\le 10^9$,时限 4s。
source: JOI 2021 Final T4 Robot
link: https://loj.ac/p/3471
思路
首先连通就有解,因为可以做到让每条边颜色各不相同。
不难发现如果我们需要走一条本来不能走的边 $u\to v$,有以下两种修改方案:
- 修改 $u\to v$ 的颜色为一条完全不同的颜色
- 修改与 $u\to v$ 同色的全部 $u$ 的出边为完全不同的颜色
假设这样的情况:$u\to v\to w$,其中两条边都是红色,那么如果在 $u\to v$ 时选择了 1,在 $v\to w$ 选择 2 时还修改 $v\to u$ 就显得很亏。
考虑建虚点。对于结点 $u$,对每种包含在它出边中的颜色 $c$ 另开一个虚点 $\lang u,c\rang$,$u\stackrel{0}\to\lang u,c\rang$,$\lang u,c\rang\stackrel{-pv+\sum\limits{u\stackrel{c}\to w} p_w}\to v$,$v\stackrel 0\to\lang u,c\rang$,$u\stackrel{p_i}\to v$。($(u,v)$ 颜色为 $c$)
正常来说,第一种修改相当于走第四种边;第二种修改相当于走第一、二种边,而特殊情况相当于走第三、二种边。
直接建图,但是要注意点数是 $O(m)$ 而非 $O(n^2)$ 的,所以可能要用 unordered_map
来做到常规的数组。
有人说 map
更快?简单测试一下:
-O0 | -O2 | |
---|---|---|
std::map |
27128ms | 34582ms |
std::unordered_map |
22148ms | 33912ms |
代码
Dijkstra 写错就离谱……
1 |
|