首页 > 代码库 > ZOJ Monthly, June 2014 解题报告

ZOJ Monthly, June 2014 解题报告

A.Another Recurrence Sequence

B.Gears

题目大意:有n个齿轮,一开始各自为一组,之后进行m次操作,包括以下4种类型:
1.合并两组齿轮,合并的两个应该反向旋转
2.把某个齿轮从所在组删除,自为一组,但不影响同组其它齿轮的状态与关系
3.询问两个齿轮是同向、反向或无关系(即不在同一组)
4.询问某个齿轮所在组的齿轮总数

分析:典型的并查集操作,但是注意两点:
1.由于操作3要询问两个齿轮的相对状态,因此对并查集中每个元素应当保存它的状态信息。状态是相对的,只需要保存每个元素相对于父元素的状态,在查询所属集合时顺便更新状态信息。如用depth[i]表示齿轮i相对于父齿轮的深度,那么两个齿轮属于同一组且深度奇偶性相同时同向旋转。更新depth数组也行简单,i对j的深度 = i对k的深度 + k对j的深度。
2.操作2涉及删除某个元素。另外开一个数组id,用id[i]表示元素i实际所在的位置,当删除元素i时,令id[i] = new id,同时fa[id[i]] = id[i],即id[i]自为一组。这样一来,之后涉及到元素i的操作都用id[i]代替,而原来的i元素依然存在,只不过它只起到占位的作用,以维持原集合的相对关系。相当于id[i]表示元素i的指针。

<script src="https://code.csdn.net/snippets/372647.js" type="text/javascript"></script>

C.Consecutive Blocks

题目大意:给定一个整数序列,要求删除最多k个数后,新序列中连续相等的子序列长度最大,输出该最大长度。

分析:除了F题搞笑外这个就是最简单的题了。记录每个数出现的位置(由于数字可能很大,先把数字映射到1..k),然后计算以每个位置结束时的最大长度即可。

D.An Easy Game

题目大意:给定两个0-1序列s1, s2,操作t次,每次改变m个位置,求把s1改变为s2的方法总数。

分析:明显的DP,注意s1和s2哪些位置相同并不重要,重要的是有几个位置不同。改变的时候也一样,改变哪些位置并不重要,重要的是改变之后有几个位置不同。所以用dp[i][j]表示i次操作之后有j个位置不同的方法数,答案就是dp[t][0]。对于dp[i - 1][j],经过一次操作之后假设把k个位置从不同变为相同,剩下m - k个位置从相同变为不同,那么
dp[i][j + m - k - k] += dp[i - 1][j] * C(j, k) * C(n - j, m - k)
其中C(j, k)表示组合数,即从j个不同的位置选出k个改变。循环k即可。

<script src="https://code.csdn.net/snippets/372660.js" type="text/javascript"></script>

E.Romantic Value

题目大意:给定一个无向图,要求删除一些边使点p和点q不连通,首先是使花费最少,若有多组解则使删除的边最少。

分析:典型的最小割,最大流即可。只需要把每边的花费c改为c = c * (|E| + 1) + 1即可使删除的边最少,其中|E|为边数。为方便把|E|换为一个较大的数也可以。

<script src="https://code.csdn.net/snippets/372661.js" type="text/javascript"></script>

F.First Digit

分析:搞笑题,就不解释了。

G.Greedy Driver

H.Grouping

题目大意:给定一个有向图,要求把点分为k个集合,使得每个集合中的任意两点a, b满足a, b互相不可到达。

分析:求出强连通分量后缩点,得到有向无环图,dfs该图求出各点深度(深度加权,权值为强连通分量大小),深度最大值即答案,因为这一条路径上任意两点都可从深度小的一点到达深度大的一点,所以必定属于不同集合;又可以把其它路径(长度为len)上的各点依次归到集合1..len。

<script src="https://code.csdn.net/snippets/372667.js" type="text/javascript"></script>

I.Left 4 Dead

J.Sister‘s Noise