【题解】Solution Set - NOIP2024集训Day18 优化建图

【题解】Solution Set - NOIP2024集训Day18 优化建图

https://www.becoder.com.cn/contest/5499


「SNOI2017」炸弹

考虑将每一次一个炸弹引爆另一个炸弹抽象成一条有向边。

然后缩点,再用 dfs 求出每个点能到达的其她点的数量。


显然边数是 \(O(n^2)\) 级别的,不能暴力连边。

注意到, 每个点向左/向右连的都是一段连续的区间。

我们直接在线段树上面维护哪些点没有被访问过,然后在线段树上直接找出来递归,然后把这个区间内没有被分配 \(scc\)\(low\) 维护区间 \(\min\),然后更新当前的 \(low\) 就行了。

然后卡在怎么最后怎么在 DAG 上面求能到达的点数。

「但是这个东西在一般的 DAG 上是个世纪难题。」好吧,世纪难题没想出来还是情有可原的。😅

但是对于这道题比较特别,最终的答案一定是一个区间,所以我们直接把每个点可以到达的点的区间并算出来就行了。

tarjan 求出来的强连通分量的标号满足 topo 序。

问题来了,最后 toposort 不太好知道每个点的连边啊(其实模仿上面的做法应该也可以),但是好麻烦 /kk。

感觉口胡的这个东西挺对的,但是很难真正的建出一张图来,然后套用图论上的一些工具。


实际上真正的线段树优化建图是这样的:

由于每个点的连边都是一个区间,我们可以把这个区间拆分成一棵满二叉树上的 \(\log n\) 个节点,这样的图和原图是完全等价的,然后就可以直接缩点,然后 toposort 直接做了。


「POI2015」PUS

线段树优化建图,然后差分约束。

虚点间的反边边权为 \(0\),实点和虚点间的边权为 \(-1\),就行了。


还有一个问题,这 \(k\) 个数每个实际上是大于 \(k\) 个区间,如果每次都暴力连这 \(k\) 个区间是肯定不行的。

实际上这 \(k\) 个区间的连边是完全相同的,我们可以直接建一个虚点连向这 \(k\) 个区间,然后再把这 \(k\) 元素连向这个虚点,这样就对了。


关于 spfa,它死了。介于这道题边权都是 \(-1/0\)。并且初始边权为 \(0\) 的边一定不会构成环,所以我们直接 topo,如果有环就一定是负环,直接无解。

其实一直对差分约束的理解都不算很清晰。

https://www.becoder.com.cn/contest/submission/2591898

这个代码实际上并不能保证所有的点都跑到,所以会出现很多 1e9。


「PA2012」Tax

好奇怪的题啊。


因为我们的权值在点上,这很难处理,我们考虑边转点、点转边。

这样很好计算边权。

对于起点我们特殊处理一下:把和起点直接相连的边变成的点和源点连边,边权就是原始的边权。终点同理。


但是问题在于我们连边的时候,对于每一个点每次都是度数的平方级别。

首先将每个点的邻接边按边权排序。

对于一个新点 \(i\),她一定会向 \(1\sim i-1\) 都连一条自己边权的边。注意到每次都是一个前缀,对于每一个前缀我们都开一个虚点来代表她,一个虚点会连向当前点和上一个虚点,边权都设为 \(0\)。这其实和线段树优化建图有异曲同工之妙,都是用虚点来代替一个区间,只是前缀更为特殊。

注意虚点之间的边不能连双向边,否则会出现莫名其妙的边权为 \(0\) 的边在实点之间。所以我们需要正反向的前缀我们都要做一遍。

最后跑一边 dijkstra 就行了。


「CF587D」Duff in Mafia

ps. 「匹配」的意思是不存在两条边有公共点。


考虑二分。

check 的话就是要对于每一条权值小于等于 \(mid\) 的边决定她选还是不选,大于 \(mid\) 的一定不能取。每条边只有两种对立的状态。想到 2-sat。

  1. 如果当前边选择,那么相邻的其她边都不能选。
  2. 如果当前边不选,那么相邻的同色的边都必选。

然后其实上面一道题很类似,还是边转点。同时对前后缀建立虚点。

\(1\sim m\) 表示当前边选择,\(m+1\sim 2m\) 表示当前边不选。

  1. 如果当前边选择,\(i\) 向下标 \([1+m, i+m)\) 连双向边。
  2. 如果当前边不选,先把那么相邻的同色放一起,然后同色内部双向连边。

posted @ 2024-08-30 08:08  CloudWings  阅读(13)  评论(0编辑  收藏  举报